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

使用Jest测试Angular 1.6服务时遇async callback未调用错误求助

解决Angular 1.6 + Jest测试中"async callback was not invoked"错误

我之前在测试Angular 1.6的服务时也碰到过一模一样的问题——明明服务里没写setTimeout,却总是触发这个异步超时报错。后来发现,罪魁祸首往往是Angular 1.x内置的异步机制(比如$http请求、$q promise),和Jest的异步检测逻辑没匹配上,下面是我总结的几个排查和修复方向:

可能的原因及修复方案

1. 没有手动触发Angular的消化周期

Angular 1.x的异步操作(比如$http返回的promise)依赖**消化周期(digest cycle)**来完成状态更新,但Jest不会自动帮你触发这个周期。哪怕promise已经resolve了,测试也感知不到,最终导致Jest判定异步回调未执行。

修复方法:在测试里手动调用$rootScope.$digest()或者$rootScope.$apply(),同时别忘了用$httpBackend.flush()刷新模拟的HTTP请求:

describe('MarvelService', () => {
  let MarvelService, $rootScope, $httpBackend;

  beforeEach(() => {
    angular.mock.module('yourAppModule');
    inject((_MarvelService_, _$rootScope_, _$httpBackend_) => {
      MarvelService = _MarvelService_;
      $rootScope = _$rootScope_;
      $httpBackend = _$httpBackend_;
      
      // 模拟Marvel API的响应
      $httpBackend.whenGET(/https:\/\/gateway.marvel.com\/.*$/).respond(200, { data: [] });
    });
  });

  it('should fetch characters successfully', (done) => {
    MarvelService.getCharacters().then((response) => {
      expect(response.data).toEqual([]);
      done(); // 告诉Jest异步操作已完成
    });
    
    $httpBackend.flush(); // 触发模拟请求的响应
    $rootScope.$digest(); // 启动Angular消化周期
  });
});

2. 测试函数未传递异步结束信号给Jest

Jest需要明确知道异步测试什么时候结束,如果你的测试包含异步逻辑(比如服务里的$q promise),要么在回调里调用done(),要么让测试函数直接返回一个promise。

比如用返回promise的简化写法:

it('should fetch characters successfully', () => {
  const promise = MarvelService.getCharacters();
  
  $httpBackend.flush();
  $rootScope.$digest();
  
  return promise.then((response) => {
    expect(response.data).toEqual([]);
  });
});

3. 未正确模拟$http请求(若服务依赖HTTP调用)

如果你的Marvel Service直接调用了真实的Marvel API,网络请求的延迟会让Jest超时。必须用$httpBackend模拟所有HTTP请求,确保请求能被立即响应。

上面示例中的$httpBackend.whenGET(...).respond(...)和$httpBackend.flush()就是关键步骤,不能省略。

4. Jest默认超时时间太短

虽然这种情况比较少见,但如果你的测试逻辑确实需要更长时间执行,可以手动延长超时时间:

it('should fetch characters successfully', (done) => {
  // ...测试逻辑
  done();
}, 10000); // 设置10秒超时(默认是5秒)

总结

绝大多数情况下,这个问题都是因为Angular消化周期未触发或者Jest没收到异步结束的信号。按照上面的步骤逐一排查,应该能快速解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 10:38:32