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

Angular服务测试中如何测试方法同步抛出的错误用例

问题场景

Angular服务中存在返回Observable类型的方法,部分校验不通过场景会直接同步抛出错误,示例代码如下:

calculateMyItem(a:number): Observable<state> {
     if (a<1){
       throw new Error('Please input valid number');
     } 

    return of({item:'item1',status:'success'});
}

编写单元测试时会发现:错误在方法调用阶段就同步抛出,触发时机早于subscribe订阅操作,订阅的错误回调完全无法捕获该错误。例如下方测试写法根本进不到错误处理逻辑,执行service.calculateMyItem(0)时就会直接抛错:

service.calculateMyItem(0).subscribe({
  error: err => console.log('error')
})
解决方法

方案1:修正服务实现,符合RxJS规范(推荐)

按照Observable的设计约定,流中所有错误都应该走Observable自身的错误通道,不应该在流外同步抛出,这样调用方可以用统一的逻辑处理同步、异步错误。
把同步throw替换为RxJS的throwError即可,修改后代码:

import { throwError, of } from 'rxjs';

calculateMyItem(a:number): Observable<state> {
     if (a<1){
       // 返回一个会发送错误通知的Observable,而非直接同步抛错
       return throwError(() => new Error('Please input valid number'));
     } 

    return of({item:'item1',status:'success'});
}

修改后常规的订阅错误回调、单元测试写法都能正常工作,测试示例:

it('should throw valid error when input number is less than 1', (done) => {
  service.calculateMyItem(0).subscribe({
    next: () => fail('should not return success response for invalid input'),
    error: (err) => {
      expect(err.message).toBe('Please input valid number');
      done();
    }
  })
})

方案2:不修改源码的测试写法

如果暂时无法调整服务代码,针对同步抛出的错误,不需要走Observable订阅逻辑,直接按照普通同步函数抛错的方式断言即可:

it('should throw valid error when input number is less than 1', () => {
  expect(() => service.calculateMyItem(0)).toThrowError('Please input valid number');
})

注意:该写法仅能捕获同步抛出的错误,如果方法后续新增异步错误逻辑,测试会直接失效。长期维护的项目优先选择方案1,统一错误处理逻辑,避免同时维护同步、异步两套错误捕获逻辑。

内容的提问来源于stack exchange,提问作者Mohsen Zahedi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:12:25