Рассмотрим эту функцию
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);
});
}
Есть ли более правильный способ достичь этого?