Как это возможно?
expect
запускается и дает сбой до того, как selectElement
сможет запустить.
Подробности
Очередь сообщений
JavaScript использует очередь сообщений .Текущее сообщение доходит до завершения до начала следующего.
Очередь PromiseJobs
ES6 представила Очередь PromiseJobs , котораяобрабатывает задания "которые являются ответами на урегулирование Обещания".Все задания в очереди PromiseJobs запускаются после завершения текущего сообщения и до начала следующего сообщения .
async / await
async
иawait
являются просто синтаксическим сахаром над обещаниями и генераторами .Вызов await
для Promise
по существу оборачивает остальную часть функции в обратный вызов, который должен быть запланирован в PromiseJobs, когда разрешается Promise
.
Что происходит
Ваш тест запускается как текущее запущенное сообщение.Вызов shallowMount
загружает ваш компонент, который работает до await this.$store.dispatch('someOtherAction');
, который вызывает someOtherFunction
, а затем, по существу, ставит в очередь остальную часть функции как Promise
обратный вызов, который будет запланирован в очереди PromiseJobs, когда Promise
разрешится.
Затем выполнение возвращается к тесту, который запускает два оператора expect
.Первое проходит с момента вызова someOtherFunction
, а второе - с ошибкой, поскольку selectElement
еще не запущено.
Затем текущее запущенное сообщение завершается и выполняются отложенные задания в очереди PromiseJobs.Обратный вызов, который вызывает selectElement
, находится в очереди, поэтому он запускается и вызывает selectElement
, который регистрируется на консоли.
Решение
Убедитесь, чтоPromise
обратный вызов, который вызывает selectElement
, выполнялся перед запуском expect
.
Когда бы ни было возможно, идеально было бы возвратить Promise
, чтобы тест мог await
его напрямую.
Если это невозможно, то обходной путь должен вызвать await
для разрешенного Promise
во время теста, который, по существу, ставит в очередь оставшуюся часть теста в конце очереди PromiseJobs и позволяет любым ожидающим обратным вызовам Promise
запускаться первым:
it('selects element if passed in route', async () => {
const $route = {params: {id: '256'}};
const wrapper = shallowMount(AbcModel, {
mocks: {$route},
store, localVue
});
expect(someOtherFunction).toHaveBeenCalled();
// Ideally await the Promise directly...
// but if that isn't possible then calling await Promise.resolve()
// queues the rest of the test at the back of PromiseJobs
// allowing any pending callbacks to run first
await Promise.resolve();
expect(selectElement).toHaveBeenCalled(); // SUCCESS
});