[英]Test rxjs interval in Angular 6 component ngOnInit function
我有一個帶有以下 ngOnInit 函數的組件,它輪詢服務方法以進行狀態更新:
ngOnInit() {
interval(2000).pipe(
switchMap(() => this.dataService.getStatus())
).subscribe((result) => {
this.uploadStatus = result;
);
}
我正在嘗試使用以下代碼測試更新是否實際發生:
beforeEach(() => {
fixture = TestBed.createComponent(UploadComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should start checking for status updates', fakeAsync(() => {
const dataService = TestBed.get(DataService);
// Mock the getStatus function
spyOn(dataService, 'getStatus').and.returnValue(Observable.create().pipe(map(() => 'woo')));
// Should not be initialised yet
expect(component.uploadStatus).toBeUndefined();
tick(2000);
expect(component.uploadStatus).toBe('woo');
}));
但是component.uploadStatus
始終為 null。 我應該如何去測試這種類型的場景? 理想情況下,我想隨着時間的推移檢查多個更新。
謝謝
我最終確定的是以下內容。 我還必須存儲訂閱,以便在測試結束時取消訂閱,以防止“定期計時器仍在隊列中”錯誤:
ngOnInit() {
// Store the subscription so we can unsubscribe when testing
this.pollingSubscription = interval(2000).pipe(
switchMap(() => this.dataService.getStatus())
).subscribe((result) => {
this.uploadStatus = result;
});
}
然后測試如下:
it(`init`, fakeAsync(inject([DataService],
(dataService: DataService) => {
const testReturns = [
of('woo'),
of('yay')
];
let currentReturn = -1;
spyOn(dataService, 'getStatus').and.callFake(() => {
currentReturn++;
return testReturns[currentReturn];
});
expect(component.uploadStatus).toBeUndefined();
fixture.detectChanges();
// expect(component.uploadStatus).toBe('Login');
// spyOn(dataService, 'getStatus').and.returnValue(of('woo'));
component.ngOnInit();
tick(2000);
expect(component.uploadStatus).toBe('woo');
tick(2000);
expect(component.uploadStatus).toBe('yay');
// Unsubscribe to prevent the "periodic timers still in queue" errors
component.pollingSubscription.unsubscribe();
})));
問題出在 Angular CLI 為您設置的beforeEach
單元測試模板中。 在第一個變更檢測周期,即在ngOnInit
,您訂閱了由interval
創建的 Observable。
訂閱必須在fakeAsync
區域內進行,以便tick
管理 Observable 的時間。 移動呼叫fixture.detectChanges
內部fakeAsync
區,你會看到tick
現在管理的時間。
beforeEach((): void => {
fixture = TestBed.createComponent(UploadComponent);
component = fixture.componentInstance;
// Get rid of call to detectChanges
});
it('should start checking for status updates', fakeAsync((): void => {
// Arrange
const dataService = TestBed.get(DataService);
spyOn(dataService, 'getStatus').and.returnValue(of('woo'));
// Assert
expect(component.uploadStatus).toBeUndefined();
// Act
fixture.detectChanges();
tick(2000);
// Assert
expect(component.uploadStatus).toBe('woo');
// Clean up RxJS.interval function
discardPeriodicTasks();
}));
您必須在勾選后觸發更改檢測,這應該可以工作
tick(2000);
fixture.detectChanges();
expect(component.uploadStatus).toBe('woo');
你可以使用setTimeout()
等待2秒(稍微多一點,因為你又在里面做異步任務),然后檢查property
值。
確保使用done()
方法通知測試運行器測試用例已完成。
it('should start checking for status updates', (done) => {
const dataService = TestBed.get(DataService);
// Mock the getStatus function
spyOn(dataService, 'getStatus').and.returnValue(Observable.create().pipe(map(() => 'woo')));
// Should not be initialised yet
expect(component.uploadStatus).toBeUndefined();
setTimeout(()=> {
expect(component.uploadStatus).toBe('woo');
done();
},2500);
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.