В React-приложениях взаимодействие с сервером часто реализуется через
axios или встроенный fetch. Тестирование таких
компонентов требует изоляции бизнес-логики от реальных сетевых
запросов, чтобы тесты оставались быстрыми, предсказуемыми и не
зависели от состояния сервера. Основные подходы —
мокирование и проверка вызовов.
axios — это библиотека, возвращающая промисы, что делает
её удобной для мокирования с помощью Jest.
Пример мокирования запроса:
import axios from 'axios';
import { render, screen, waitFor } from '@testing-library/react';
import UsersList from './UsersList';
jest.mock('axios');
test('загружает и отображает список пользователей', async () => {
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
axios.get.mockResolvedValue({ data: users });
render( );
// Ожидание, пока элементы появятся в DOM
for (const user of users) {
await waitFor(() => expect(screen.getByText(user.name)).toBeInTheDocument());
}
// Проверка, что axios.get был вызван один раз с правильным URL
expect(axios.get).toHaveBeenCalledWith('/api/users');
});
Ключевые моменты:
jest.mock('axios') подменяет все методы
axios на мок-функции.mockResolvedValue позволяет имитировать успешный ответ
с данными.waitFor используется для асинхронного ожидания
изменений в DOM.axios.get гарантирует корректность
параметров запроса.fetch встроен в браузеры, поэтому для тестирования его
чаще всего подменяют с помощью Jest или библиотеки
jest-fetch-mock.
Пример с Jest:
import { render, screen, waitFor } from '@testing-library/react';
import UsersList from './UsersList';
beforeEach(() => {
global.fetch = jest.fn();
});
afterEach(() => {
jest.resetAllMocks();
});
test('загружает и отображает список пользователей через fetch', async () => {
const users = [
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' },
];
fetch.mockResolvedValue({
ok: true,
json: async () => users,
});
render( );
for (const user of users) {
await waitFor(() => expect(screen.getByText(user.name)).toBeInTheDocument());
}
expect(fetch).toHaveBeenCalledWith('/api/users');
});
Особенности мокирования fetch:
fetch.mockResolvedValue возвращает объект с полями
ok и json(), имитирующий реальный
Response.mockRejectedValue или ok: false с
соответствующей логикой обработки.Важно проверять корректную обработку ошибок:
test('отображает сообщение об ошибке при сбое запроса', async () => {
axios.get.mockRejectedValue(new Error('Network Error'));
render( );
await waitFor(() => expect(screen.getByText(/ошибка/i)).toBeInTheDocument());
});
Для fetch аналогично:
fetch.mockRejectedValue(new Error('Network Error'));
Основные моменты:
waitFor.При тестировании компонентов, использующих axios или
fetch:
Мокировать запросы до рендера компонента.
Использовать waitFor или
findBy* селекторы для асинхронного ожидания
появления данных.
Проверять:
Стараться не тестировать сам axios или fetch, а лишь логику компонента, зависящую от данных запроса.
Иногда необходимо тестировать несколько последовательных запросов или ожидание:
axios.get
.mockResolvedValueOnce({ data: [{ id: 1, name: 'Alice' }] })
.mockResolvedValueOnce({ data: [{ id: 2, name: 'Bob' }] });
render( );
await waitFor(() => expect(screen.getByText('Alice')).toBeInTheDocument());
await waitFor(() => expect(screen.getByText('Bob')).toBeInTheDocument());
Преимущества:
Использование этой структуры делает тесты читаемыми и поддерживаемыми, особенно при сложных компонентах с множеством асинхронных операций.