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

Angular单元测试中Observable用例断言错误仍正常通过的问题排查

问题核心原因

你的单元测试没有正确处理异步逻辑,Jasmine默认按照同步逻辑执行测试用例:subscribe 回调需要等Observable异步返回结果才会执行,但Jasmine在执行完apiService.goToPurchases(null).subscribe(...)这行代码后就直接标记测试用例执行完成,回调里的断言代码根本没有运行,所以无论断言写的是否符合预期,测试都会显示通过。

另外你当前的测试还存在两个额外问题:

  • 单元测试不应发起真实HTTP请求,需要用Angular提供的HttpClientTestingModule拦截并Mock请求结果,否则测试可用性会依赖后端服务状态
  • 断言字段拼写错误:你写的res.shimentId少了一个字母p,正确字段名是res.shipmentId

修复方案

1. 引入测试工具,正确模拟HTTP请求

首先在测试模块的导入配置中加入HttpClientTestingModule,并注入HttpTestingController用于拦截请求。

2. 正确处理异步测试逻辑,可选两种写法

写法1:使用done回调标记异步测试结束
fdescribe('goToPurchases', () => {
  let httpTestingController: HttpTestingController;
  // 省略其他服务注入逻辑

  it('should have working NavApiService', (done) => { // 传入done回调
    apiService.goToPurchases(null).subscribe((res: PurchaseResponse) => {
      expect(res.shipmentId).toBe('not supposed to be valid!')
      expect(res.url).not.toBeDefined();
      done(); // 回调执行完成后通知Jasmine测试结束
    });

    // 拦截请求返回Mock数据,主动触发回调执行
    const req = httpTestingController.expectOne(`${environmentVariables.loadInsurance.apiUrl}/v1/purchases`);
    expect(req.request.method).toBe('POST');
    req.flush({
      "id": "50d4ad69-0337-4e49-8f00-5c9a152cfad0",
      "shipmentId": null,
      "userId": "41ac2d3d-b2ed-4c73-9c56-25d17a9caa7e",
      "url": "https://test.portal.loadsure.net/insureLoad/v2?id=TFMtREFULzIwMjEwODMxL3l6ZDVlYlJRejdrQkdKcUwxbk5l"
    });
  });

  afterEach(() => {
    httpTestingController.verify(); // 验证所有预期请求都已触发
  });
});
写法2:使用fakeAsync+tick处理异步
it('should have working NavApiService', fakeAsync(() => {
  let result: PurchaseResponse | undefined;
  apiService.goToPurchases(null).subscribe((res: PurchaseResponse) => {
    result = res;
  });

  const req = httpTestingController.expectOne(`${environmentVariables.loadInsurance.apiUrl}/v1/purchases`);
  req.flush({
    "id": "50d4ad69-0337-4e49-8f00-5c9a152cfad0",
    "shipmentId": null,
    "userId": "41ac2d3d-b2ed-4c73-9c56-25d17a9caa7e",
    "url": "https://test.portal.loadsure.net/insureLoad/v2?id=TFMtREFULzIwMjEwODMxL3l6ZDVlYlJRejdrQkdKcUwxbk5l"
  });
  tick(); // 触发所有异步回调执行

  expect(result?.shipmentId).toBe('not supposed to be valid!')
  expect(result?.url).not.toBeDefined();
}));

修改后运行测试,回调内的断言就会正常执行,不符合预期的情况下会抛出错误。

内容的提问来源于stack exchange,提问作者Julio Rodríguez

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 20:30:01