【问题标题】:Test rxjs interval in Angular 6 component ngOnInit function在 Angular 6 组件 ngOnInit 函数中测试 rxjs 间隔
【发布时间】:2019-03-08 19:14:00
【问题描述】:

我有一个带有以下 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 始终为空。我应该如何去测试这种类型的场景?理想情况下,我想随着时间的推移检查多个更新。

谢谢

【问题讨论】:

    标签: angular unit-testing jasmine rxjs


    【解决方案1】:

    我最终确定的是以下内容。我还必须存储订阅,以便在测试结束时取消它,以防止出现“周期性计时器仍在队列中”错误:

    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();
    })));
    

    【讨论】:

      【解决方案2】:

      问题在于 Angular CLI 为您设置的单元测试模板的 beforeEach。在第一个变更检测周期,即ngOnInit 中,您订阅了interval 创建的 Observable。

      订阅必须在fakeAsync 区域内进行,以便tick 管理 Observable 的时间。将呼叫移至fakeAsync 区域内的fixture.detectChanges,您将看到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();
      }));
      

      【讨论】:

        【解决方案3】:

        您必须在勾选后触发更改检测,这应该可以工作

        tick(2000);
        fixture.detectChanges();
        expect(component.uploadStatus).toBe('woo');
        

        【讨论】:

          【解决方案4】:

          您可以使用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);
          
          });
          

          【讨论】:

            猜你喜欢
            • 2021-06-22
            • 2016-08-09
            • 2018-11-14
            • 1970-01-01
            • 1970-01-01
            • 2020-08-08
            • 2016-05-25
            • 2021-06-27
            • 2017-11-20
            相关资源
            最近更新 更多