Проблема
Могут быть и другие проблемы с вашим тестом, но я рассмотрю конкретный вопрос, который вы задали по поводу expect(mockedOnSuccess).toHaveBeenCalledTimes(1);
, с ошибкой 0 times
:
jest.runAllTimers
будетсинхронно запускать любые ожидающие обратные вызовы таймера, пока не останется больше.Это выполнит анонимную функцию, запланированную с setTimeout
в runPolling
.Когда анонимная функция выполняется, она вызовет api.request(url)
, но , и это все, что произойдет .Все остальное в анонимной функции содержится в обратных вызовах then
, которые ставятся в очередь в PromiseJobs
очереди заданий, представленной в ES6 .Ни одно из этих заданий не будет выполнено к тому времени, когда jest.runAllTimers
вернется и тест продолжится.
expect(mockAxios.request).toHaveBeenCalledTimes(1);
затем пройдет, так как api.request(url)
выполнено.
expect(mockedOnSuccess).toHaveBeenCalledTimes(1);
, затем произойдет сбой, так какthen
обратный вызов, который вызвал бы его, все еще находится в очереди PromiseJobs
и еще не выполнен.
Решение
Решение состоит в том, чтобы убедиться, что задания поставлены в очередь в PromiseJobs
иметь возможность запустить, прежде чем утверждать, что mockedOnSuccess
был вызван.
К счастью, очень легко разрешить выполнение любых ожидающих заданий в PromiseJobs
в рамках теста async
в Jest
, просто вызовитеawait Promise.resolve();
.По существу, это ставит в очередь оставшуюся часть теста в конце PromiseJobs
и позволяет первым выполнить любые ожидающие задания в очереди:
test('runPolling should be called recursively when onSuccess returns true', async () => {
...
jest.runAllTimers();
await Promise.resolve(); // allow any pending jobs in PromiseJobs to execute
expect(mockAxios.request).toHaveBeenCalledTimes(1);
expect(mockedOnSuccess).toHaveBeenCalledTimes(1); // SUCCESS
...
}
Обратите внимание, что в идеале асинхронная функция будет возвращать обещание, которое может выполнить тесттогда жди.В вашем случае у вас запланирован обратный вызов с setTimeout
, поэтому нет способа вернуть Обещание для ожидания теста.
Также обратите внимание, что у вас есть несколько цепочек обратных вызовов then
, так что вы можетенужно ждать ожидающих заданий несколько раз во время теста PromiseJobs
.
Подробнее о том, как фальшивые таймеры и Обещания взаимодействуют здесь .