Skip to main content

模拟计时器

模拟计时器

jest.spyOn

该方法用于模拟对象或者类的方法,并且可以监控这些方法的调用情况:

const myApi = {
async fetchUser(id) {
const response = await fetch(`/api/user/${id}`);
const user = await response.json();
return user;
}
};

test('fetches user data', async () => {
// 监视了 myApi 对象的 fetchUser 方法
const spy = jest.spyOn(myApi, 'fetchUser');
// 通过 spy 重新定义了该方法的返回值,从而达到一个更好的控制
spy.mockResolvedValue({ name: 'John', age: 30 });

const user = await myApi.fetchUser(123);

expect(user).toEqual({ name: 'John', age: 30 });
expect(spy).toHaveBeenCalledWith(123);

spy.mockRestore();
});
  • jest.spyOn用于监视对象的方法,可以监视被测试代码中的某一个方法是否被正确的调用,另外还可以控制所监视的方法的行为。
  • jest.mock常用于一个模块的导入,可以在测试中替换掉被测试代码中所依赖的模块。

模拟setInterval

模拟测试setInterval,需要使用jest.useFakeTimers方法,方法的作用是提供了一个模拟的计时器对象,可以模拟时间的流逝。

假设代码中有一个setTimeout,该计时器是5秒后触发,如果使用真实的计时器,那么需要等待5秒,而如果使用模拟的计时器对象,那么可以对时间进行一个快进操作。

使用了jest.useFakeTimers,模拟了计时器之后,后面需要将计时器还原,可以使用jest.useRealTimers:

如下是一个模拟setInterval的测试示例:

export function startTimer(
callback: () => void,
interval: number
): NodeJS.Timeout {
const timerId = setInterval(() => {
callback()
}, interval)
return timerId
}

export function clearTimer(timerId: NodeJS.Timeout) {
clearInterval(timerId)
}
  • 通过调用jest.useFakeTimers,使用模拟的计时器对象,其能够控制时间的流逝,在beforeEach里面调用,使其会在每一个测试用例开始之前对计时器对象进行替换。
  • 通过调用jest.useRealTimers,将模拟的计时器对象还原为真实的计时器对象,在afterEach里面调用,使其会在每一个测试用例结束之后换回来。
  • 使用jest.spyOn来监听setInterval方法,并且替换为了模拟的setInterval,这样可以避免调用真实的setInterval

模拟setTimeout

setTimeoutsetInterval类似:

export function startTimeout(
callback: () => void,
timeout: number
): NodeJS.Timeout {
const timerId = setTimeout(() => {
callback()
}, timeout)

return timerId
}

export function stopTimeout(timerId: NodeJS.Timeout) {
clearTimeout(timerId)
}