You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular+Jest中RxJS catchError与subscribe场景测试问题排查

解决Angular组件中someAction方法的Jest测试问题

问题场景

组件中的someAction方法逻辑如下:

someAction(ids: string[]): void {
    this.testService
      .someActionFromService(ids)
      .pipe(
        catchError((error) => {
          this.close(); // 组件方法
          return throwError(() => error);
        }),
      )
      .subscribe(() => {
        this.close();
        // 调用其他组件方法
      });
}

对应的Jest测试代码:

describe('someAction(): ', () => {
    it('des', fakeAsync(() => {
      fixture.detectChanges();
      const testServiceSpy = testService.someActionFromService.mockReturnValue(new Observable()); // 服务已提前正确Mock
      const closeSpy = jest.spyOn(component, 'close');
      component.someAction(['id1']);
      fixture.detectChanges();
      tick(1000);
      fixture.detectChanges();
      expect(testServiceSpy).toHaveBeenCalledWith(['id1']);
      // 此处断言失败:close未被调用
      expect(closeSpy).toHaveBeenCalled();
    }));
});

测试报错:

expect(jest.fn()).toHaveBeenCalled()

    Expected number of calls: >= 1
    Received number of calls:    0

问题原因

你当前用new Observable() mock服务返回值,这个Observable既不会发出任何数据,也不会完成或抛出错误,导致subscribe的成功回调和catchError的错误回调都不会被触发,自然close方法不会被调用。

解决方案

需要根据测试场景,mock出能触发对应回调的Observable:

1. 测试成功场景(触发subscribe回调)

用of()创建一个会立即发出值并完成的Observable:

testService.someActionFromService.mockReturnValue(of({}));

2. 测试错误场景(触发catchError回调)

用throwError()创建一个会立即抛出错误的Observable:

testService.someActionFromService.mockReturnValue(throwError(() => new Error('test error')));

完整测试示例

describe('someAction(): ', () => {
    it('should call close on successful service response', fakeAsync(() => {
      fixture.detectChanges();
      // Mock成功响应
      testService.someActionFromService.mockReturnValue(of({}));
      const closeSpy = jest.spyOn(component, 'close');
      
      component.someAction(['id1']);
      tick(); // 触发Observable的异步操作
      fixture.detectChanges();
      
      expect(testService.someActionFromService).toHaveBeenCalledWith(['id1']);
      expect(closeSpy).toHaveBeenCalledTimes(1);
    }));

    it('should call close on service error', fakeAsync(() => {
      fixture.detectChanges();
      // Mock错误响应
      testService.someActionFromService.mockReturnValue(throwError(() => new Error('test error')));
      const closeSpy = jest.spyOn(component, 'close');
      
      component.someAction(['id1']);
      tick(); // 触发Observable的异步操作
      fixture.detectChanges();
      
      expect(testService.someActionFromService).toHaveBeenCalledWith(['id1']);
      expect(closeSpy).toHaveBeenCalledTimes(1);
    }));
});

注意:tick()不需要传1000,因为of和throwError都是同步触发的Observable,用tick()即可完成异步调度。

内容的提问来源于stack exchange,提问作者Aastha B

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 13:15:08