簡體   English   中英

在Angular 6組件ngOnInit函數中測試rxjs間隔

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM