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

如何使用Jest模拟异步函数延迟并测试异步函数顺序执行逻辑

Jest测试异步函数调用顺序的正确姿势

你的测试核心问题在于:Jest的jest.runAllTimers()只会触发宏任务(比如setTimeout),但await后的Promise回调属于微任务,不会被自动执行;再加上测试没有等待异步流程完成,导致断言时机不对。

以下是修正后的完整测试代码:

test('Should not call second function until first function resolved', async () => {
  jest.useFakeTimers();
  const spyOnFuncA = jest.spyOn(module2, 'funcA').mockImplementation(() => 
    new Promise(resolve => setTimeout(resolve, 1000))
  );
  const spyOnFuncB = jest.spyOn(module2, 'funcB').mockImplementation();

  // 启动异步函数但不等待
  mainFunc();

  // 第一个断言:funcA已调用,funcB未调用
  expect(spyOnFuncA).toHaveBeenCalled();
  expect(spyOnFuncB).not.toHaveBeenCalled();

  // 快进所有定时器(触发funcA的Promise resolve)
  jest.runAllTimers();

  // 等待微任务队列清空(让await funcA()后的代码执行)
  await Promise.resolve();

  // 第二个断言:funcB已被调用
  expect(spyOnFuncB).toHaveBeenCalled();

  // 清理mock,避免影响其他测试
  spyOnFuncA.mockRestore();
  spyOnFuncB.mockRestore();
  jest.useRealTimers();
});

关键要点说明

  • 测试函数必须标记为async:因为需要等待微任务完成后再做断言
  • 等待微任务:await Promise.resolve()会让JavaScript引擎先处理完当前所有微任务(也就是await funcA()之后的funcB()调用逻辑)
  • 清理mock和定时器:测试结束后恢复原始函数和真实定时器,防止污染其他测试用例
  • mock简化:不需要给funcA的mock加async关键字,直接返回Promise即可,效果一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 03:25:12