古いコードはrxjs v5.5.12を使用しています。rxjsv6.4.0を使用する新しいプロジェクトに同じコードをコピーしました。テストケースを実行しようとすると、このエラーが発生します。
旧コード:
import * as ObservableEvents from 'rxjs/Observable/fromEvent';
spyOn(ObservableEvents, 'fromEvent').and.returnValue(new Subject<any>().asObservable());
新しいコード:
import * as rxjs from 'rxjs';
spyOn(rxjs, 'fromEvent').and.returnValue(new Subject<any>().asObservable());
どちらの場合も、次のエラーが発生します。
エラー::fromEventは書き込み可能として宣言されていないか、セッターがありません
この問題を解決するための有効なリソースが見つかりませんでした。
アップデート#1
使ってみた
import * as rxjs from 'rxjs';
spyOn(jasmine.createSpyObj(rxjs), 'fromEvent').and.returnValue(new Subject<any>().asObservable());
今回は、
createSpyObjは、スローされるスパイを作成するためにメソッド名の空でない配列またはオブジェクトを必要とします
アップデート#2:
@ Omair-Nabielのコードを使用しましたが、新しいエラーが発生しました
TypeError: Object(...) is not a function
at XxxPopoverDirective.fromEvent [as createPopover] (http://xxx:xxxx/src/app/shared/xxx/xxx.directive.ts?:113:37)
at XxxPopoverDirective.createPopover [as mouseClick] (http://xxx:xxxx/src/app/shared/xxx/xxx.directive.ts?:70:14)
at runTest (http://xxx:xxxx/src/app/shared/xxx/xxx.directive.spec.ts?:181:19)
xxx.directive.ts
line 113-> this.componentRef && this.componentRef.destroy();
this.componentRef = null;
line 70-> constructor(
...
private resolver: ComponentFactoryResolver,
...
) { }
アップデート#
こんにちはOmair Nabiel、私たちが使用している以下のコードを見つけてください、解決策を教えてください、
file = "popover.directive.ts"コード:
import { fromEvent } from 'rxjs/Observable/fromEvent';
this.clickOutSub = fromEvent(this.documentRef.getDocument(), 'click').subscribe(this.clickOut.bind(this));
file="popover.directive.spec.ts"
Code:
import * as ObservableEvents from 'rxjs/Observable/fromEvent';
function runTest() {
spyOn(ObservableEvents, 'fromEvent').and.returnValue(new Subject<any>().asObservable());
}
it('...', () => {
expect(ObservableEvents.fromEvent).toHaveBeenCalled();
});
モジュールの読み込みは読み取り専用であるため、スパイすることはできません。 ここにあります 同じrxjsの問題と Jasmineの問題 がGitHubにあります。
しかし、本当にfromEvent
関数をスパイしたいですか?あなたの目的が、クラス/関数がfromEvent
を呼び出すかどうかをチェックすることである場合、これを行うべきではありません。テストではAPIをテストする必要がありますが、実装はテストしません。そのようなテスト、つまり実装をテストすることを維持することは困難です。ブラックボックスをテストする必要があり、ブラックボックスの実装方法について考えるべきではありません。
テスト内でfromEvent
を使用する場合、その動作をテストすることは問題ではないはずです。いずれにしても、イベントをオブザーバブルに変換する方法をテストすることが重要である場合は、次のように 'fromEvent'ラッパーを作成してモックできます。
class EventTransformer {
transform<T>(target: FromEventTarget<T>, eventName: string): Observable<T> {
return fromEvent(target, eventName);
}
}
class MyClass {
constructor(private eventTransformer: EventTransformer) {}
doSomething() { /* transform some event */ }
}
it('test', () => {
const eventTransformer = jasmine.createSpyObj<EventTransformer>(EventTransformer.name, [
'transform',
]);
eventTransformer.transform.and.returnValue(of({}));
const myClass = new MyClass(eventTransformer)
myClass.doSomething();
});
別の回避策 は、テスト用のtsconfigを更新して「commonjs」モジュールを使用することです。
"compilerOptions": {
....
// force commonjs module output, since it let mock exported members on modules to anywhere in the application (even in the same file)
"module": "commonjs",
},
Rxjsのプロパティをスパイする必要があります。 spyOnPropertyを使用すると、エラーが解決します。これを試して
import * as rxjs from 'rxjs'
import { of, fromEvent } from 'rxjs';
spyOnProperty(rxjs, 'fromEvent').and.returnValue(of({}))
このようにゲッター/セッターに追加することもできます
spyOnProperty(rxjs, 'fromEvent', 'get').and.returnValue(false)
お役に立てれば
Omairの回答を補完します。私の場合、returnValue
ステートメントに関数が必要です。
const fromEventSpy = spyOnProperty(rxjs, 'fromEvent').and.returnValue(() => rxjs.of({}));
乾杯!