Тестирование async-кода
Урок показывает три способа тестировать асинхронный код в Jest и типичную ошибку с ним.
Главное правило: тест должен дождаться завершения асинхронной операции, иначе Jest посчитает его пройденным раньше времени.
Главная ловушка
Если в тесте есть промис, но вы его не дождались, Jest завершит тест до того, как проверка выполнится — и тест ложно «пройдёт». Поэтому асинхронность нужно явно ждать.
Способ 1: async/await
Самый читаемый вариант — пометить тест async и использовать await:
async function fetchUser(id) {
return { id, name: 'Аня' }; // в реальности — запрос к API
}
test('возвращает пользователя по id', async () => {
const user = await fetchUser(1);
expect(user.name).toBe('Аня');
});Способ 2: вернуть промис
Если вернуть промис из теста, Jest сам дождётся его. Удобны матчеры resolves и rejects:
test('промис резолвится в имя', () => {
return expect(fetchUser(1)).resolves.toEqual({ id: 1, name: 'Аня' });
});
test('запрос несуществующего бросает', () => {
return expect(fetchUser(-1)).rejects.toThrow('Not found');
});Не забывайте return (или await) — без него промис не дождётся.
Способ 3: колбэк done
Для старого колбэк-API есть параметр done: тест считается завершённым, только когда вы его вызовете:
test('колбэк вызывается с данными', (done) => {
loadData((err, data) => {
expect(data).toBe('ok');
done(); // сообщаем Jest: тест завершён
});
});Сегодня async/await предпочтительнее, но done полезен для событийных и колбэк-интерфейсов.
Почему нужно ждать — на чистом JS
Покажем, как await меняет порядок выполнения:
function fetchUser(id) {
return Promise.resolve({ id, name: 'Аня' });
}
async function run() {
console.log('1: до await');
const user = await fetchUser(1);
console.log('2: получили', user.name);
console.log('3: проверка пройдена:', user.name === 'Аня');
}
run();
console.log('синхронный код после run()');Вывод:
1: до await синхронный код после run() 2: получили Аня 3: проверка пройдена: true
Обратите внимание: строка «синхронный код после run()» печатается до получения данных. Если бы тест не дождался промиса, проверка (строка 3) не успела бы выполниться — именно поэтому в Jest обязательно await/return.
Итог
- Асинхронный тест обязан дождаться операции, иначе пройдёт ложно.
async/await— самый читаемый способ.resolves/rejectsпроверяют исход промиса; не забывайтеreturn/await.done— для колбэк- и событийного API.