考虑此功能
function startTimerWithAsyncCallback(
firstAsyncFunction,
secondAsyncFunction,
thirdAsyncFunction,
millis,
) {
setTimeout(async () => {
await firstAsyncFunction();
await secondAsyncFunction();
await thirdAsyncFunction();
}, millis);
}
我想测试使用超时时间的假计时器在超时后调用3个异步函数。
test('fake timers', () => {
jest.useFakeTimers();
const firstAsyncFunction = jest.fn();
const secondAsyncFunction = jest.fn();
const thirdAsyncFunction = jest.fn();
startTimerWithAsyncCallback(
firstAsyncFunction,
secondAsyncFunction,
thirdAsyncFunction,
1000,
);
jest.advanceTimersByTime(2000);
expect(firstAsyncFunction).toHaveBeenCalled();
expect(secondAsyncFunction).toHaveBeenCalled(); // FAILS HERE !
expect(thirdAsyncFunction).toHaveBeenCalled();
});
在此测试中,第一个异步函数处于挂起状态,而下一个异步函数未调用。我没有找到一种方法来断言:在进行断言之前“等待setTimeout的回调完成”
我想出了一种变通方法,它可以还原实际计时器,并在声明前等待0毫秒。
test('fake timers and restore real timers', async () => {
jest.useFakeTimers();
const firstAsyncFunction = jest.fn();
const secondAsyncFunction = jest.fn();
const thirdAsyncFunction = jest.fn();
startTimerWithAsyncCallback(
firstAsyncFunction,
secondAsyncFunction,
thirdAsyncFunction,
1000,
);
jest.advanceTimersByTime(2000);
expect(firstAsyncFunction).toHaveBeenCalled();
await waitAsyncFunctionsToComplete(); // WORKAROUND
expect(secondAsyncFunction).toHaveBeenCalled();
expect(thirdAsyncFunction).toHaveBeenCalled();
});
async function waitAsyncFunctionsToComplete() {
jest.useRealTimers();
await delay(0);
jest.useFakeTimers();
}
async function delay(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
有没有更合适的方法来实现这一目标?
答案 0 :(得分:0)
如Mark Meyer在评论中所建议,使startTimerWithAsyncCallback
返回Promise更易于测试
function startTimerWithAsyncCallback(
firstAsyncFunction,
secondAsyncFunction,
thirdAsyncFunction,
millis,
) {
return new Promise((resolve) => { // <==
setTimeout(async () => {
await firstAsyncFunction();
await secondAsyncFunction();
await thirdAsyncFunction();
resolve(); // <==
}, millis);
});
}
describe('Using async callbacks with timers', () => {
test('fake timers', async () => {
jest.useFakeTimers();
const firstAsyncFunction = jest.fn();
const secondAsyncFunction = jest.fn();
const thirdAsyncFunction = jest.fn();
const promise = startTimerWithAsyncCallback( // <==
firstAsyncFunction,
secondAsyncFunction,
thirdAsyncFunction,
1000,
);
jest.advanceTimersByTime(2000);
await promise; <==
expect(firstAsyncFunction).toHaveBeenCalled();
expect(secondAsyncFunction).toHaveBeenCalled();
expect(thirdAsyncFunction).toHaveBeenCalled();
});
});