Выпуск
toast.present()
по-прежнему находится в очереди в PromiseJobs
и не запускается к тому времени, когда expect
подтверждает и завершается ошибкой.
Решение
Пусть любые обратные вызовы, поставленные в очередь в PromiseJobs
, выполняются перед утверждением:
it('should make a call to login fire a toast if there is an error', async () => {
authService.login.mockReturnValue(throwError({}));
await component.login(); // await login
expect(loadingCtrl.create).toHaveBeenCalled();
expect(loadingInstance.present).toHaveBeenCalled();
expect(loadingInstance.dismiss).toHaveBeenCalled();
expect(toastCtrl.create).toHaveBeenCalledWith({
message: 'Failed to log in',
position: 'top',
cssClass: 'error-toast'
});
await Promise.resolve(); // allow pending callbacks in PromiseJobs to run
expect(toastInstance.present).toHaveBeenCalled(); // SUCCESS
});
Подробности
Обратные вызовы, переданные в subscribe
, не являются частью component.login
, поэтомуобратные вызовы могут выполняться, а могут и не выполняться, когда Promise
, возвращенный из component.login
, разрешается и тест продолжается.
В этом случае вызывается обратный вызов error
и выполняется вызов create
но остальная часть обратного вызова еще не запущена к тому моменту, когда expect(toastInstance.present).toHaveBeenCalled();
запускается и завершается неудачей.
В идеале непосредственно тестирует await
любой тестируемый асинхронный код, но так как это невозможно с асинхронным обратным вызовом, в качестве альтернативыозначает await
разрешенное значение Promise
, которое, по существу, ставит в очередь оставшуюся часть теста в конце PromiseJobs
за любыми ожидающими обратными вызовами, давая другим функциям обратного вызова возможность выполнить перед продолжением теста.
Примечание: Вы могли заметить, чтоt Jest
полностью выходил с необработанным исключением вместо того, чтобы просто сообщить, что тест не пройден.То, как тест написан в вопросе, Promise
, возвращаемое из component.login().then()
, не возвращается и не await
-ed, поэтому тест завершается, и неудачный expect
в обратном вызове then
в конечном итоге происходит вне теста, вызываяJest
для выхода.Самый простой способ решить эту проблему (реализовано в приведенном выше решении) - удалить обратный вызов then
и просто await
Promise
, возвращенный из component.login
перед началом expect
утверждений.