如何用Jest结合useFakeTimers测试含setTimeout的异步函数?
解决Jest虚拟时间测试异步休眠函数的问题
你的测试超时是因为调用await systemUnderTest()时,fake timers会阻塞setTimeout的执行,导致Promise一直处于pending状态,测试自然会超时。正确的做法是先触发函数执行,再运行虚拟定时器,最后等待函数完成,具体实现如下:
正确测试代码
test('myTest', async () => { jest.useFakeTimers(); // 启动函数但不立即等待,此时函数执行到await处暂停 const promise = systemUnderTest(); // 运行所有虚拟定时器,触发setTimeout回调使Promise resolve jest.runAllTimers(); // 等待函数执行完成 await promise; jest.useRealTimers(); });
原理说明
- 先调用
systemUnderTest()但不await,函数会打印"One",随后遇到await new Promise(...)暂停执行,此时Promise处于pending状态。 - 调用
jest.runAllTimers()会立即执行所有被fake timers拦截的定时器回调,触发setTimeout的resolve函数,让之前的Promise变为resolved状态,函数继续执行并打印"Two"。 - 最后
await promise等待整个函数执行完成,确保测试流程正常结束。
可选优化:精准执行单个定时器
如果你的函数包含多个定时器,只想执行当前pending的1秒休眠定时器,可以用jest.runOnlyPendingTimers()替代jest.runAllTimers(),避免意外执行其他未预期的定时器:
test('myTest', async () => { jest.useFakeTimers(); const promise = systemUnderTest(); jest.runOnlyPendingTimers(); await promise; jest.useRealTimers(); });
内容的提问来源于stack exchange,提问作者carlo.milanesi
相关产品推荐
相关产品推荐

