Jest 测试时如何 mock setTimeout/setInterval?

阅读时长 4 分钟读完

在前端开发中,我们经常需要使用 setTimeoutsetInterval 待定时器来执行一些异步操作,但当进行单元测试时, 这样的异步操作会导致测试的不确定性,因为测试的结果取决于待定时器何时被执行,而测试端无法控制待定时器的执行时间。 Jest提供了一些API来帮助我们在测试时模拟这些待定时器。

Jest 提供的 mock 定时器 API

Jest 提供了两个事件轮询的 mock API:jest.useFakeTimers()jest.runAllTimers()jest.useFakeTimers() 主要用于直接替换 setInterval、setTimeout 和 clearTimeout / clearInterval,使得在我们不必等待实际速度而直接运行测试的情况下,重建我们的循环事件和时间逻辑。可以调用 jest.runAllTimers() 来强制执行所有待定的定时器或者 jest.runOnlyPendingTimers() 来只执行待执行的定时器。

当使用 jest.useFakeTimers()后,测试时周期事件轮询的定时器不再是真正的定时器,而是被完全控制的事件轮询模拟器。那么如何模拟setTimeoutsetInterval呢?

模拟 setTimeout

我们可以使用 jest.runAllTimers() 来模拟 setTimeout。它会立即将所有待执行的定时器达成的效果都执行,因此我们可以通过向 setTimeout 传递一个函数作为回调,然后手动的调用 jest.runAllTimers() 来立即执行定时器中的所有回调函数。

比如设在测试代码中,有一个函数 delayAndReturn ,它将在两秒后返回一个数字 1。函数实现如下:

在测试代码中,我们可以使用以下方式来测试该函数:

模拟 setInterval

我们也可以使用 jest.runOnlyPendingTimers() 命令来模拟 setInterval。它会只执行当前待执行的定时器,而不是所有。

比如设在测试代码中,有一个函数 logMessage ,它将每秒 log 一条 message。函数实现如下:

在测试代码中,我们可以使用以下方式来测试该函数:

-- -------------------- ---- -------
---------------- ---- - ------- ----- -------- -- -- -
  ---------------------
  ----- ---------- - ------------------- -------
  ----- ------------ - -------------

  ------------------------------------------

  ----------------------------
  --------------------------------------------

  ----------------------------
  --------------------------------------------

  ---------------
---

总结

Jest 提供了事件轮询 mock API 来模拟待定时器,帮助我们在使用待定时器时进行单元测试。在测试中,我们使用jest.useFakeTimers来替换setTimeoutsetInterval ,使用jest.runAllTimers强制执行所有待执行的定时器,以执行回调函数,使用 jest.runOnlyPendingTimers()来强制执行所有待执行的定时器,以确保函数能够按预期工作。加入这些应该让你能够更方便地测试异步代码,并且保证它们能够在团队内部和客户内部进行工作。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/647ea88448841e9894e5c2f9

纠错
反馈