Мокирование HTTP-запросов является ключевым элементом тестирования
компонентов, которые взаимодействуют с внешними API. В экосистеме React
Testing Library (RTL) чаще всего используется библиотека
axios для выполнения запросов. Прямое выполнение реальных
HTTP-запросов во время тестов нежелательно: это снижает их скорость,
делает результаты нестабильными и создаёт зависимость от внешних
сервисов. Мокирование решает эти проблемы, позволяя контролировать
ответы и имитировать ошибки.
Существует несколько распространённых способов мокирования
axios в тестах:
Использование jest.mock Jest позволяет
автоматически подменять модули через jest.mock. Это
наиболее простой и часто используемый способ.
import axios from 'axios';
import { render, screen, waitFor } from '@testing-library/react';
import MyComponent from './MyComponent';
jest.mock('axios');
test('отображает данные после запроса', async () => {
const mockData = { data: { message: 'Привет, мир!' } };
axios.get.mockResolvedValueOnce(mockData);
render(<MyComponent />);
const element = await screen.findByText(/Привет, мир!/i);
expect(element).toBeInTheDocument();
});
Ключевые моменты:
jest.mock('axios') подменяет все методы
axios на jest-функции.mockResolvedValueOnce задаёт конкретный ответ для
одного вызова.mockRejectedValueOnce.Создание отдельного мок-файла При большом проекте удобно вынести моки в отдельный файл. Например:
// __mocks__/axios.js
const axios = {
get: jest.fn(),
post: jest.fn(),
put: jest.fn(),
delete: jest.fn(),
};
export default axios;
Jest автоматически подхватывает такой файл при вызове
jest.mock('axios'). Это позволяет централизованно управлять
всеми HTTP-запросами в тестах.
Использование axios-mock-adapter Для более
сложных сценариев, когда нужно мокировать разные эндпоинты и методы с
разными ответами, удобна библиотека axios-mock-adapter.
import axios from 'axios';
import MockAdapter from 'axios-mock-adapter';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
test('axios-mock-adapter пример', async () => {
const mock = new MockAdapter(axios);
mock.onGet('/api/message').reply(200, { message: 'Привет, мир!' });
render(<MyComponent />);
const element = await screen.findByText(/Привет, мир!/i);
expect(element).toBeInTheDocument();
});
Преимущества axios-mock-adapter:
.reply(500) или
.networkError().Компоненты, использующие axios, почти всегда асинхронны.
В React Testing Library асинхронные операции проверяются с помощью
findBy* и waitFor.
Пример обработки ошибки:
test('отображает сообщение об ошибке при неудачном запросе', async () => {
axios.get.mockRejectedValueOnce(new Error('Сервер недоступен'));
render(<MyComponent />);
const errorElement = await screen.findByText(/Сервер недоступен/i);
expect(errorElement).toBeInTheDocument();
});
Рекомендации по асинхронным тестам:
findBy* автоматически ждёт появления элемента до
заданного таймаута.waitFor используется для проверки изменений состояния,
которые не сразу отражаются в DOM.В больших проектах рекомендуется создавать утилиты для мокирования запросов. Пример:
// test-utils/axiosMock.js
import axios from 'axios';
export const mockAxiosGet = (url, response) => {
axios.get.mockImplementation((requestUrl) => {
if (requestUrl === url) {
return Promise.resolve({ data: response });
}
return Promise.reject(new Error('Неизвестный URL'));
});
};
Использование в тесте:
import { mockAxiosGet } from './test-utils/axiosMock';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
test('использует утилиту мокирования', async () => {
mockAxiosGet('/api/message', { message: 'Привет!' });
render(<MyComponent />);
const element = await screen.findByText(/Привет!/i);
expect(element).toBeInTheDocument();
});
Такой подход делает тесты более читаемыми и уменьшает дублирование кода.
Отсутствие await или использования
findBy* при проверке асинхронного контента. В
результате тест проходит, но компонент не успевает обновить
DOM.
Неправильное использование mockResolvedValue
вместо mockResolvedValueOnce. Если тестов
несколько, глобальный мок может влиять на другие тесты.
Зависимость от внешних данных. Мокирование необходимо для всех запросов, чтобы тесты были детерминированными.
Неправильное восстановление состояния мока между
тестами. Рекомендуется использовать
beforeEach(() => jest.clearAllMocks()) для очистки
моков.
Мокирование axios в React Testing Library позволяет
полностью контролировать поведение компонентов при различных сценариях
взаимодействия с API, ускоряет тесты и повышает их стабильность.
Правильная организация моков и использование асинхронных утилит RTL
обеспечивают надёжность и читаемость тестового кода.