javascript单元测试中模拟定时器需用jest fake timers:先jest.usefaketimers()启用,再用runalltimers()执行全部待触发回调,或advancetimersbytime(ms)精确推进时间;setinterval需手动clearinterval或用advancetimersbytimerepeatedly()处理重复触发;必要时jest.userealtimers()还原原生定时器。

在 JavaScript 单元测试中模拟定时器(setTimeout / setInterval)并快进时间,核心是使用 Jest 提供的 fake timers 功能。它能替换全局定时器为可控版本,让你跳过真实等待,直接推进时间、触发回调。
启用 fake timers
在测试文件顶部或 beforeEach 中启用:
-
jest.useFakeTimers();—— 启用后,所有setTimeout、setInterval等将被拦截,不真实执行 - 推荐搭配
jest.clearAllTimers()和jest.restoreAllMocks()在afterEach中清理,避免测试间干扰
快进时间:runAllTimers vs advanceTimersByTime
两种常用推进方式,适用不同场景:
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
-
jest.runAllTimers();—— 立即执行所有已注册但尚未触发的定时器回调(包括嵌套、递归的),适合“等所有异步逻辑跑完” -
jest.advanceTimersByTime(ms);—— 将虚拟时钟向前拨动指定毫秒数,只触发在此期间到期的定时器,更精确,适合验证“1s 后做了什么” - ⚠️ 注意:
advanceTimersByTime不会自动处理重复定时器(如setInterval)的多次触发,需配合循环或advanceTimersByTimeRepeatedly(Jest 29.7+)
处理 setInterval 的重复执行
setInterval 默认不会因 runAllTimers 被清空(它会持续注册新任务)。稳妥做法:
- 显式保存 timer ID,并在测试中
clearInterval(id)清理 - 用
jest.advanceTimersByTime(n)多次推进,例如每 100ms 触发一次,推进 300ms 就执行 3 次 - Jest 29.7+ 可用
jest.advanceTimersByTimeRepeatedly(ms, times)简化重复推进 - 示例:
jest.advanceTimersByTimeRepeatedly(100, 3); // 执行 3 次 100ms 间隔的回调
还原真实定时器(可选)
如果某个测试需要恢复原生行为(比如测性能或兼容性):
-
jest.useRealTimers();—— 切回浏览器/Node 原生定时器 - 通常放在
afterAll或特定test结尾,避免影响后续测试










