MSW (Mock Service Worker) — это библиотека для имитации сетевых запросов в браузере и Node.js. Она позволяет перехватывать HTTP-запросы на уровне Service Worker и возвращать заранее заданные ответы, что делает тестирование компонентов и API-зависимого функционала максимально предсказуемым и изолированным от реального сервера.
Для начала необходимо установить пакет:
npm install msw --save-dev
Создаются два ключевых файла: handlers.js и server.js (для Node) или browser.js (для фронтенда).
Пример handlers.js:
import { rest } from 'msw';
export const handlers = [
rest.get('/api/users', (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json([
{ id: 1, name: 'Alice' },
{ id: 2, name: 'Bob' }
])
);
}),
rest.post('/api/login', (req, res, ctx) => {
const { username } = req.body;
if (username === 'admin') {
return res(ctx.status(200), ctx.json({ token: '12345' }));
} else {
return res(ctx.status(403), ctx.json({ error: 'Forbidden' }));
}
})
];
Настройка для Node.js (server.js):
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
Настройка для браузера (browser.js):
import { setupWorker } from 'msw';
import { handlers } from './handlers';
export const worker = setupWorker(...handlers);
При тестировании компонентов React необходимо обеспечить корректный жизненный цикл mock-сервера. Обычно используют хуки Jest:
import { server } from './server';
import { render, screen, waitFor } from '@testing-library/react';
import UserList from './UserList';
// Включение перехвата запросов до всех тестов
beforeAll(() => server.listen());
// Сброс обработчиков после каждого теста
afterEach(() => server.resetHandlers());
// Отключение сервера после всех тестов
afterAll(() => server.close());
test('отображает список пользователей', async () => {
render(<UserList />);
await waitFor(() => {
expect(screen.getByText('Alice')).toBeInTheDocument();
expect(screen.getByText('Bob')).toBeInTheDocument();
});
});
MSW позволяет изменять поведение mock-сервера прямо в тестах для проверки ошибок или разных сценариев:
import { rest } from 'msw';
import { server } from './server';
test('обрабатывает ошибку сервера', async () => {
server.use(
rest.get('/api/users', (req, res, ctx) => {
return res(ctx.status(500), ctx.json({ error: 'Internal Server Error' }));
})
);
render(<UserList />);
await waitFor(() => {
expect(screen.getByText(/ошибка/i)).toBeInTheDocument();
});
});
Компоненты React часто зависят от асинхронных запросов. MSW идеально
интегрируется с async/await и методами React Testing
Library (waitFor, findBy*):
const button = screen.getByRole('button', { name: /загрузить/i });
fireEvent.click(button);
const userItem = await screen.findByText('Alice'); // автоматически ждёт появления
expect(userItem).toBeInTheDocument();
MSW позволяет одинаково тестировать как фронтенд, так и серверные
функции, вызывающие API. Для Node используется setupServer,
для браузера — setupWorker. Это гарантирует одинаковое
поведение тестов и минимизирует зависимость от внешних API.
ctx.status и ctx.delay().MSW является мощным инструментом для создания надежного тестового окружения, где поведение сетевых запросов полностью контролируется, а тесты остаются стабильными и предсказуемыми.