最近、Angular 5からAngular 6に更新され、それにRxJs 6が追加されました。移行の一環として、タイマーの使用法が次のように変更されました。
Observable.timer()
に
timer()
テストでは、タイマーのオブザーバブルを次のパターンで模擬する場所がいくつかあります。
let timerObserver: Observer<any>;
beforeEach(() => {
spyOn(Observable, 'timer').and.returnValue(Observable.create(
((observer: Observer<any>) => {
timerObserver = observer;
})
));
});
it(`should not have any notifications by default`, () => {
timerObserver.next('');
...
});
誰かがこのパターンを移行する方法を知っていますか?
編集:ここに問題の簡略図を作成しました:
https://stackblitz.com/edit/angular-v6-testing-template-nm7add
// Hello.Component
ngOnInit() {
const timer$ = timer(30);
timer$.subscribe(() => {
this.testMe = 'this has been changed';
});
}
// Hello.component.spec
it('should set testMe after a given timer', fakeAsync(() => {
tick(50);
expect(fixture.componentInstance.testMe).toBe('this has been changed');
}));
この例では、タイマーが解決するのを待たずにタイマーをトリガーしようとしています。
fakeAsync
を使用しているので、setInterval
のパッチ適用に依存して、timer
オブザーバブルの実装を偽ることができます。
ただし、asyncScheduler
インスタンスのnow
メソッドはDate.now()
を返すため、これを上書きする必要があります。 (厳密に言えば、これはtimer
オブザーバブルを使用したので必須ではありませんが、他のオブザーバブル(たとえば、delay
演算子によって返されるオブザーバブル)にとっては重要です)。
beforeEach
とafterEach
を使用してnow
メソッドを上書きし、偽の時間を追跡する関数を構成すると、物事をかなり簡単に機能させることができます。
import { fakeAsync, tick as _tick } from '@angular/core/testing';
import { asyncScheduler, of, timer } from 'rxjs';
import { delay } from 'rxjs/operators';
describe('fakeAsync and RxJS', () => {
let tick: (milliseconds: number) => void;
beforeEach(() => {
let fakeNow = 0;
tick = milliseconds => {
fakeNow += milliseconds;
_tick(milliseconds);
};
asyncScheduler.now = () => fakeNow;
});
it('should support timer with fakeAsync', fakeAsync(() => {
const source = timer(100);
let received: number | undefined;
source.subscribe(value => received = value);
tick(50);
expect(received).not.toBeDefined();
tick(50);
expect(received).toBe(0);
}));
it('should support delay with fakeAsync', fakeAsync(() => {
const source = of(0).pipe(delay(100));
let received: number | undefined;
source.subscribe(value => received = value);
tick(50);
expect(received).not.toBeDefined();
tick(50);
expect(received).toBe(0);
}));
afterEach(() => {
delete asyncScheduler.now;
});
});
実際、時間ベースのオブザーバブルをモックするためにfakeAsync
に依存することは有用である可能性が高いため、fakeSchedulers
関数を私の rxjs-marbles
に追加しましたパッケージ。使用例については fake-spec.ts
を参照してください。
実装は基本的に上記のスニペットと同じです-関数にラップされるだけです。
この回答を書いてfakeSchedulers
をrxjs-marbles
に追加して以来、私は Testing with Fake Time に関する記事を書きました。