Тестирование компонентов и логики в JavaScript, которые выполняют
асинхронные запросы, требует мокирования HTTP-запросов. Библиотеки,
такие как fetch и axios, часто используются
для работы с API. Мокирование этих запросов позволяет изолировать тесты
от реальных серверных зависимостей, повышая скорость тестов и
стабильность среды.
В Enzyme, вместе с Jest, мокирование HTTP-запросов — это неотъемлемая часть настройки тестов, особенно если компоненты или функции взаимодействуют с внешними API.
fetchfetch — это стандартный метод для выполнения
HTTP-запросов в современных браузерах. В тестах важно предотвратить
реальное выполнение запросов, заменив их моками. Мокирование позволяет
контролировать поведение запросов, а также задавать имитацию ответов с
серверов.
fetch:Jest предоставляет встроенную функцию jest.fn(), которая
позволяет заменить вызовы fetch на моки. Для этого
достаточно использовать метод global.fetch.
beforeAll(() => {
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: 'test' }),
})
);
});
it('должен вызвать fetch и вернуть данные', async () => {
const response = await fetch('/api/data');
const data = await response.json();
expect(fetch).toHaveBeenCalledTimes(1);
expect(data.data).toBe('test');
});
В данном примере мы заменили глобальный fetch на мок,
который всегда возвращает успешный ответ с данными
{ data: 'test' }. Тест проверяет, что fetch
был вызван и данные были правильно извлечены.
Можно также имитировать ошибки, которые могут возникать при запросах, например, если сервер недоступен или произошла ошибка на стороне API.
beforeAll(() => {
global.fetch = jest.fn(() =>
Promise.reject(new Error('Network error'))
);
});
it('должен обрабатывать ошибку при вызове fetch', async () => {
try {
await fetch('/api/data');
} catch (e) {
expect(e.message).toBe('Network error');
}
});
Здесь мы подменяем fetch на мок, который всегда вызывает
ошибку. Тест проверяет, что ошибка корректно обрабатывается.
Когда необходимо проверить, с какими параметрами был вызван
fetch, можно использовать expect для
утверждений.
beforeAll(() => {
global.fetch = jest.fn(() =>
Promise.resolve({
json: () => Promise.resolve({ data: 'test' }),
})
);
});
it('должен передавать правильные параметры в fetch', async () => {
await fetch('/api/data', {
method: 'POST',
body: JSON.stringify({ id: 1 }),
});
expect(fetch).toHaveBeenCalledWith(
'/api/data',
expect.objectContaining({
method: 'POST',
body: JSON.stringify({ id: 1 }),
})
);
});
Здесь мы проверяем, что fetch был вызван с правильными
параметрами — методом POST и телом запроса, сериализованным
в JSON.
axiosaxios — это популярная библиотека для выполнения
HTTP-запросов, которая часто используется в React-компонентах и других
JavaScript-приложениях. Мокирование axios имеет свои
особенности, но в целом процесс схож с мокированием
fetch.
axios:Для мокирования axios можно использовать
jest.mock для замены всей библиотеки на поддельную
реализацию, которая возвращает заранее заданные данные.
import axios from 'axios';
jest.mock('axios');
it('должен делать запрос с axios и возвращать данные', async () => {
axios.get.mockResolvedValue({ data: { message: 'test' } });
const response = await axios.get('/api/data');
expect(axios.get).toHaveBeenCalledWith('/api/data');
expect(response.data.message).toBe('test');
});
В данном примере мы заменяем вызов axios.get на моку,
которая всегда возвращает данные с полем message, равным
‘test’. Тест проверяет, что запрос был выполнен и данные были корректно
возвращены.
Для имитации ошибки при запросе через axios используется
метод mockRejectedValue, который позволяет задавать
отклонённые промисы.
import axios from 'axios';
jest.mock('axios');
it('должен обрабатывать ошибку с axios', async () => {
axios.get.mockRejectedValue(new Error('Network error'));
try {
await axios.get('/api/data');
} catch (e) {
expect(e.message).toBe('Network error');
}
});
Здесь мы подменяем axios.get на мок, который вызывает
ошибку с сообщением ‘Network error’. В тесте проверяется корректная
обработка этой ошибки.
Так же, как и с fetch, можно проверять параметры
запроса, переданные в axios.
import axios from 'axios';
jest.mock('axios');
it('должен передавать правильные параметры в axios', async () => {
await axios.post('/api/data', { id: 1 });
expect(axios.post).toHaveBeenCalledWith('/api/data', { id: 1 });
});
Тест проверяет, что при вызове axios.post с данными
{ id: 1 }, метод был вызван с правильными параметрами.
mswЕсли проект требует более сложного мокирования HTTP-запросов или
симуляции поведения реального сервера, можно использовать библиотеку
msw (Mock Service Worker). Эта библиотека позволяет
имитировать серверные ответы на уровне Service Worker, что делает
мокирование более гибким и реалистичным.
import { rest } from 'msw';
import { server } from './server'; // конфигурация MSW
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
it('должен обработать запрос через MSW', async () => {
server.use(
rest.get('/api/data', (req, res, ctx) => {
return res(ctx.json({ message: 'test' }));
})
);
const response = await fetch('/api/data');
const data = await response.json();
expect(data.message).toBe('test');
});
В этом примере создаётся сервер с помощью MSW, который перехватывает HTTP-запросы и отвечает заданными данными. Это особенно полезно для тестирования сложных сценариев с асинхронными запросами и сложными ответами от API.
fetch подходит для более
простых случаев, когда нужно просто заменить глобальную функцию и
контролировать её поведение.axios — это полезный
способ тестировать запросы через популярную библиотеку, предлагающую
более удобный API для работы с HTTP.Все эти подходы могут использоваться в зависимости от требований тестируемого приложения и сложности взаимодействия с сервером.