При тестировании асинхронного кода с использованием Jest часто встречается необходимость проверки результатов работы промисов. Jest предоставляет несколько специальных матчеров, которые позволяют легко тестировать промисы и асинхронные функции, возвращающие эти промисы. Эти матчеры упрощают проверку успешных и неуспешных завершений асинхронных операций, а также их результатов.
Jest поддерживает несколько основных матчеров, которые позволяют удобно работать с промисами. Вот наиболее важные из них:
resolvesЭтот матчев используется для проверки успешного выполнения промиса. Он позволяет проверить, что промис был выполнен без ошибок и его результат соответствует ожидаемому значению.
Пример использования:
test('проверка успешного результата промиса', () => {
return expect(Promise.resolve('данные')).resolves.toBe('данные');
});
В данном примере мы проверяем, что промис, разрешённый со значением
'данные', действительно возвращает это значение.
Можно комбинировать resolves с другими матчерами, чтобы
проверить более сложные результаты:
test('проверка успешного результата промиса с использованием других матчеров', () => {
return expect(Promise.resolve({ name: 'John' })).resolves.toEqual({ name: 'John' });
});
rejectsМатчер rejects используется для проверки того, что
промис был отклонён с ошибкой. Этот матчев позволяет проверить, что
асинхронная операция завершилась с ошибкой и соответствует ожидаемому
значению.
Пример использования:
test('проверка отклонённого промиса', () => {
return expect(Promise.reject(new Error('Ошибка'))).rejects.toThrow('Ошибка');
});
Здесь мы проверяем, что промис отклоняется с ошибкой, содержащей
сообщение 'Ошибка'.
resolves и rejects с другими матчерамиМожно комбинировать resolves и rejects с
другими матчерами для более точной проверки. Например, можно
использовать toBe для проверки конкретных значений или
toThrow для проверки типов ошибок.
test('проверка промиса с использованием toBe', () => {
return expect(Promise.resolve(42)).resolves.toBe(42);
});
test('проверка отклонённого промиса с использованием toThrow', () => {
return expect(Promise.reject(new Error('неудача'))).rejects.toThrow('неудача');
});
async и awaitКогда тестируем асинхронные функции с использованием
async и await, важно помнить, что промисы
нужно обрабатывать правильно, используя ожидаемые матчеры. Рассмотрим
пример:
test('тестирование асинхронной функции с использованием async/await', async () => {
const response = await someAsyncFunction();
expect(response).toBe('результат');
});
В данном примере мы использовали конструкцию await для
ожидания выполнения промиса и проверили результат с помощью матчеров
Jest. Важно, что в этом случае не нужно использовать
resolves или rejects, так как
await уже позволяет работать с результатами промисов
напрямую.
Если асинхронная функция может вызвать исключение, можно использовать
try/catch:
test('тестирование асинхронной функции с ошибкой', async () => {
try {
await someAsyncFunctionThatFails();
} catch (error) {
expect(error).toEqual(new Error('неудача'));
}
});
При работе с асинхронным кодом и промисами в Jest важно учитывать несколько аспектов, которые могут повлиять на корректность тестирования.
Время выполнения промиса. Jest ожидает, что
промис будет завершён до конца теста. Если промис не завершится до того,
как тест завершится, это приведёт к неудаче. Всегда возвращайте промис
или используйте async/await, чтобы гарантировать
выполнение.
Обработка ошибок. Промисы, отклонённые с
ошибкой, должны быть обработаны правильно. Использование
rejects помогает убедиться, что отклонённый промис
возвращает ошибку с нужным сообщением или типом.
Тестирование сетевых запросов. В случае
тестирования асинхронных сетевых запросов, например, с использованием
библиотеки axios, часто используется мокирование (mocking)
запросов, чтобы избежать реальных HTTP-вызовов в тестах. Это позволяет
быстро проверять, что промисы обрабатываются корректно в разных
ситуациях.
Пример мокирования сетевого запроса:
jest.mock('axios');
test('тестирование промиса с сетевым запросом', async () => {
axios.get.mockResolvedValue({ data: 'данные' });
const response = await axios.get('/api');
expect(response.data).toBe('данные');
});
Здесь мы мокируем метод get из библиотеки
axios, чтобы не делать реальный запрос, а вместо этого
сразу получать заранее подготовленные данные.
Для сложных тестов, где результат промиса может зависеть от времени
или дополнительных условий, можно использовать такие функции, как
setTimeout и mockResolvedValueOnce, для
тестирования временных зависимостей.
Пример с использованием setTimeout:
test('тестирование промиса с задержкой', () => {
const delayedPromise = new Promise(resolve => setTimeout(() => resolve('готово'), 100));
return expect(delayedPromise).resolves.toBe('готово');
});
Этот тест проверяет, что промис разрешится через 100 миллисекунд и вернёт ожидаемое значение.
Пример использования mockResolvedValueOnce для
мокирования одного конкретного промиса:
jest.mock('axios');
axios.get.mockResolvedValueOnce({ data: 'тест' });
test('проверка одного вызова с мокированным значением', async () => {
const response = await axios.get('/api/test');
expect(response.data).toBe('тест');
});
Матчеры для промисов в Jest значительно упрощают тестирование
асинхронного кода. Использование таких инструментов, как
resolves и rejects, позволяет легко проверять
успешные и неуспешные завершения промисов, а также их результаты.
Правильная организация тестов с промисами и их мокирование позволяют
эффективно тестировать сложные асинхронные сценарии без необходимости
обращения к реальным внешним сервисам.