返回

Jest 使用 Fake Timers 后,setTimeout 到底是什么?

前端

Jest是一个流行的JavaScript测试框架,它提供了许多有用的功能来帮助你编写和运行测试。其中一个功能就是Fake Timers,它允许你控制JavaScript中的时间函数,以便在测试中模拟时间流逝。

然而,在使用Jest的Fake Timers时,你可能会遇到一些意外的行为。例如,你可能会发现setTimeout仍然作为一个宏任务执行,即使你已经使用了Fake Timers。这是因为Fake Timers并不会真正改变setTimeout的执行顺序,它只是提供了一种模拟时间流逝的方式。

为了更好地理解setTimeout在Jest中的行为,让我们通过一个实际的例子来看看。假设你有一个这样的测试用例:

test('setTimeout should be a macro task', () => {
  jest.useFakeTimers();
  setTimeout(() => {
    expect(true).toBe(true);
  }, 0);

  // Advance the fake timers by 100ms
  jest.advanceTimersByTime(100);

  // Now the expect statement should be executed
  expect(true).toBe(true);
});

在这个测试用例中,我们使用了jest.useFakeTimers()来模拟时间流逝。然后,我们使用setTimeout()函数设置了一个超时函数,并在100毫秒后执行。接下来,我们使用jest.advanceTimersByTime(100)来推进假定的时间100毫秒。最后,我们使用expect()来断言true等于true。

你会发现,这个测试用例会通过。这表明,即使我们使用了Fake Timers,setTimeout仍然作为一个宏任务执行。这是因为Fake Timers并不会真正改变setTimeout的执行顺序,它只是提供了一种模拟时间流逝的方式。

因此,在使用Jest的Fake Timers时,你需要注意setTimeout仍然作为一个宏任务执行。如果你希望在测试中模拟setTimeout的微任务行为,你需要使用jest.runAllTimers()函数来显式地运行所有的计时器。

总结一下,Jest中的setTimeout函数在使用Fake Timers后仍然作为一个宏任务执行。如果你希望在测试中模拟setTimeout的微任务行为,你需要使用jest.runAllTimers()函数来显式地运行所有的计时器。