let a =1;let b =2;functionfun() {setTimeout(() => { a =2;setTimeout(() => { b =3;fun(); // 定时器里递归调用定时器 },2000); },1000);}// error, 不能使用 runAllTimers 方法test('test', () => {jest.useFakeTimers();fun();jest.runAllTimers();expect(a).toBe(2);expect(b).toBe(3);});
这个时候应该使用 runOnlyPendingTimers
let a = 1;
let b = 2;
function fun() {
setTimeout(() => {
a = 2;
setTimeout(() => {
b = 3;
fun();
}, 2000);
}, 1000);
}
test('test', () => {
jest.useFakeTimers();
expect(a).toBe(1);
expect(b).toBe(2);
fun();
jest.runOnlyPendingTimers(); // 加速第一个定时器
expect(a).toBe(2); // 正确
expect(b).toBe(3); // 错误,第二个定时器还没执行
jest.runOnlyPendingTimers(); // 加速第二个定时器
expect(b).toBe(3); // 正确
});
另外,我们可以通过 advanceTimersByTime(time) 来指定加速多久。
还是这个例子:
let a =1;let b =2;functionfun() {setTimeout(() => { a =2;setTimeout(() => { b =3;fun(); },2000); },1000);}// 错误// 即当我们加速 1s 的时候,只有第一个定时器会执行test('test', () => {jest.useFakeTimers();fun();jest.advanceTimersByTime(1000);expect(a).toBe(2);expect(b).toBe(3); // 应该是 2});// 正确// 而当我们加速 3s 的时候,两个定时器都会执行// 因此 a, b 的值都会发生变化test('test', () => {jest.useFakeTimers();fun();jest.advanceTimersByTime(3000);expect(a).toBe(2);expect(b).toBe(3);});
以上定时器的测试例子,同样适用于测试 React 组件,如某个操作发生,需要 setTimeout 一定时间之后才改变 state 的场景。