Настройка MSW для Jest среды

MSW (Mock Service Worker) — инструмент для перехвата сетевых запросов на уровне сервис-воркера или node-среды. В контексте тестирования с Jest MSW позволяет полностью контролировать ответы API, изолировать тесты от внешних сервисов и повысить стабильность тестов. Ниже описан подробный процесс интеграции MSW в среду Jest.


Установка зависимостей

Для работы с MSW в node-среде необходимо установить два основных пакета:

npm install msw --save-dev
npm install @testing-library/react @testing-library/jest-dom --save-dev
  • msw — основной пакет для создания обработчиков запросов.
  • @testing-library/react и @testing-library/jest-dom — вспомогательные библиотеки для тестирования React-компонентов.

Для запуска тестов в среде Node (Jest) используется node-request-interception, встроенная возможность MSW. Настройка браузерного сервис-воркера не требуется.


Создание обработчиков (handlers)

Обработчики определяют, какие запросы перехватывать и какие ответы возвращать. Структура обработчика проста:

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;
    return res(
      ctx.status(200),
      ctx.json({ token: `token-for-${username}` })
    );
  })
];
  • rest.get, rest.post и другие методы определяют HTTP-метод запроса.
  • req содержит параметры запроса, заголовки и тело.
  • res создаёт ответ, а ctx предоставляет вспомогательные методы для формирования статуса, заголовков и тела.

Важно использовать чистые, предсказуемые ответы, чтобы тесты оставались детерминированными.


Настройка сервера MSW для Jest

Для node-среды создаётся отдельный сервер:

import { setupServer } from 'msw/node';
import { handlers } from './handlers';

export const server = setupServer(...handlers);

setupServer принимает список обработчиков и создаёт сервер, который будет управлять всеми перехваченными запросами во время тестов.


Инициализация и завершение работы сервера

Чтобы сервер корректно работал с Jest, необходимо использовать хуки beforeAll, afterEach и afterAll:

// jest.setup.js
import { server } from './server';
import '@testing-library/jest-dom/extend-expect';

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
  • server.listen() — запускает перехват запросов перед тестами.
  • server.resetHandlers() — сбрасывает любые временные обработчики, добавленные внутри отдельных тестов.
  • server.close() — завершает работу сервера после всех тестов, освобождая ресурсы.

Важно подключить этот файл в конфигурации Jest:

"setupFilesAfterEnv": ["<rootDir>/jest.setup.js"]

Модификация обработчиков для конкретного теста

MSW позволяет временно изменять поведение API для отдельного теста:

import { server } from './server';
import { rest } from 'msw';

test('обрабатывает ошибку сервера', async () => {
  server.use(
    rest.get('/api/users', (req, res, ctx) => {
      return res(ctx.status(500));
    })
  );

  // логика теста, проверка обработки ошибки
});
  • server.use() добавляет новые обработчики только для текущего теста.
  • Остальные тесты остаются изолированными благодаря server.resetHandlers().

Особенности интеграции с React Testing Library

При тестировании компонентов React с асинхронными запросами важно использовать функции RTL:

  • findBy* для ожидания элементов после завершения запроса.
  • waitFor для контроля состояния компонента.

Пример теста с MSW и React Testing Library:

import { render, screen } from '@testing-library/react';
import UsersList from './UsersList';

test('отображает список пользователей', async () => {
  render(<UsersList />);

  const alice = await screen.findByText('Alice');
  const bob = await screen.findByText('Bob');

  expect(alice).toBeInTheDocument();
  expect(bob).toBeInTheDocument();
});

В этом примере MSW перехватывает запрос к /api/users и возвращает заранее определённый список, что делает тест полностью независимым от реального API.


Советы по поддержке тестовой среды

  • Разделять handlers на разные модули для разных сущностей (пользователи, авторизация, продукты).
  • Использовать ctx.delay() для симуляции сетевой задержки.
  • Всегда сбрасывать временные обработчики между тестами для предотвращения влияния одного теста на другой.
  • Логи запросов и ответов можно включать через ctx.log() для отладки сложных сценариев.

Эта настройка создаёт надёжное и предсказуемое окружение для тестирования React-приложений, позволяя полностью контролировать сетевое взаимодействие внутри Jest.