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

为何Jest异步测试在legacy假计时器下正常,modern假计时器却失效?

为何Jest的legacy假计时器正常运行,modern假计时器却失效?

以下测试使用Jest的legacy假计时器能正常通过,但切换到默认的modern假计时器就会出现问题:

jest.useFakeTimers({ legacyFakeTimers: true }); // 正常运行
// jest.useFakeTimers(); // 无法运行

it('simpleTimer', async () => {
  async function simpleTimer(callback) {
    await callback();
    setTimeout(() => {
      simpleTimer(callback);
    }, 1000);
  }

  const callback = jest.fn();
  await simpleTimer(callback);
  for (let i = 0; i < 8; i++) {
    jest.advanceTimersByTime(1000);
    await Promise.resolve(); // 允许PromiseJobs队列中的待处理任务执行
  }
  expect(callback).toHaveBeenCalledTimes(9);  // 测试通过
});

该测试示例来自Stack Overflow,我已尝试原帖中几乎所有解决方案,也参考过讨论Jest假计时器与Promise兼容的相关帖子。

使用modern假计时器时,终端会一直阻塞,必须输入^C才能终止。我还尝试过以下几种处理Promise队列的方法:

// 1
const flushPromises = () => new Promise(setImmediate);
// 2
const timeout = (ms) => // 用于类似`await timeout(1000)`的等待
  new Promise(resolve => {
    setTimeout(resolve, ms)
  });
// 3
await new Promise(process.nextTick);

目前已经找不到新的搜索方向,我的环境版本:

  • Node.JS: v18.15.0
  • Jest: v29.5.0

原本我的setup文件中仅包含jest.useFakeTimers(),后来发现setup文件和测试文件中都调用了该方法,于是移除了setup文件中的调用,只保留一处。之后收到新的报错:

thrown: "Exceeded timeout of 5000 ms for a test.
Add a timeout value to this test to increase the timeout, if this is a long-running test. See Jest docs for test timeout."

但切换回jest.useFakeTimers({ legacyFakeTimers: true })后,测试又恢复正常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 02:20:13