Тестирование компонентов, работающих с асинхронными запросами, требует моделирования реальных условий работы сети. Одним из важных аспектов является задержка ответа сервера. Без корректной симуляции медленной сети тесты могут не выявить проблемы с отображением состояния загрузки, обработкой ошибок или некорректным обновлением интерфейса.
jest.fn() и mockImplementationДля контроля задержек в асинхронных функциях удобно использовать
мок-функции. Например, при тестировании компонента, который делает
запрос через fetch:
global.fetch = jest.fn();
beforeEach(() => {
fetch.mockClear();
});
test('отображает индикатор загрузки при медленном ответе', async () => {
fetch.mockImplementation(() =>
new Promise(resolve =>
setTimeout(() => resolve({ json: () => Promise.resolve({ data: 'ok' }) }), 1000)
)
);
render(<MyComponent />);
expect(screen.getByText(/загрузка/i)).toBeInTheDocument();
await waitFor(() => expect(screen.getByText(/ok/i)).toBeInTheDocument());
});
Ключевые моменты:
mockImplementation позволяет задать любую асинхронную
логику.setTimeout эмулирует задержку сети.waitFor гарантирует корректное ожидание обновления DOM
после асинхронной операции.msw для более реалистичного мокирования APIБиблиотека Mock Service Worker (msw) предоставляет гибкий способ эмуляции сетевых запросов, включая задержки, ошибки и динамические ответы.
import { rest } from 'msw';
import { setupServer } from 'msw/node';
const server = setupServer(
rest.get('/api/data', (req, res, ctx) => {
return res(
ctx.delay(1500), // задержка 1.5 секунды
ctx.json({ data: 'response from server' })
);
})
);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
test('проверяет работу компонента с медленной сетью', async () => {
render(<MyComponent />);
expect(screen.getByText(/загрузка/i)).toBeInTheDocument();
const item = await screen.findByText(/response from server/i);
expect(item).toBeInTheDocument();
});
Преимущества msw:
ctx.delay() симулирует любую длительность ответа.Эмуляция медленной сети позволяет тестировать следующие состояния:
Индикатор загрузки Компонент должен отображать спиннер или текст «Загрузка» до получения ответа.
Обработка ошибок С помощью мока можно возвращать ошибки после задержки и проверять, что компонент корректно отображает сообщение об ошибке.
fetch.mockImplementation(() =>
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Сбой сети')), 500)
)
);
render(<MyComponent />);
expect(screen.getByText(/загрузка/i)).toBeInTheDocument();
await waitFor(() => expect(screen.getByText(/сбой сети/i)).toBeInTheDocument());
findBy* и waitFor — основные инструменты
для работы с компонентами, зависящими от асинхронных данных.
findBy* автоматически ждёт появления элемента в DOM с
таймаутом по умолчанию 1000 мс.waitFor позволяет задавать свои условия ожидания и
таймауты:await waitFor(() => {
expect(screen.getByText(/данные загружены/i)).toBeInTheDocument();
}, { timeout: 2000 });
Это особенно важно при тестировании компонентов, которые показывают прогресс загрузки или используют анимации.
setTimeout или ctx.delay,
сохраняя относительное поведение.waitFor с findBy*, чтобы корректно
обрабатывать все этапы загрузки.С помощью этих подходов тесты становятся максимально близкими к реальным сценариям работы сети, выявляют потенциальные ошибки отображения, обеспечивают надежность интерфейса и позволяют безопасно менять логику асинхронных операций без риска регрессий.