web-dev-qa-db-ja.com

エラー:<spyOn>:fromEventが書き込み可能として宣言されていないか、セッターがありません

古いコードは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();
});
11
Raju

モジュールの読み込みは読み取り専用であるため、スパイすることはできません。 ここにあります 同じ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",
},
2
Valeriy Katkov

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)

お役に立てれば

1
Omair Nabiel

Omairの回答を補完します。私の場合、returnValueステートメントに関数が必要です。

const fromEventSpy = spyOnProperty(rxjs, 'fromEvent').and.returnValue(() => rxjs.of({}));

乾杯!

0