Назад
Назад к заметкам
· 4 мин чтения

Unit-тесты в React: практический пример для 2025

Практический гайд по unit-тестам в React: настройка Jest, работа с RTL и MSW, снимки и типичные ошибки.

reacttestingjestrtlmsw

Unit-тесты в React фиксируют ожидаемое поведение сразу после написания кода. Когда в проекте уже десятки компонентов, каждый скрытый баг превращается в большую головную боль, поэтому надежный набор тестов обязателен.

Иногда можно попробовать сначала отрефакторить код, чтобы упростить тестирование. Подробнее о рефакторинге в статье Рефакторинг кода в React 2025: практический подход.

1. Подготовка окружения: Jest + React Testing Library

Самый популярный стек остается актуальным: Jest тест-раннер, и React Testing Library (RTL) утилита для работы с DOM. Установить все одной командой:

npm i -D jest @testing-library/react @testing-library/jest-dom

Для TypeScript добавьте ts-jest и создайте jest.config.js:

module.exports = {
  preset: "ts-jest",
  testEnvironment: "jsdom",
  setupFilesAfterEnv: ["<rootDir>/jest.setup.ts"],
};

В jest.setup.ts подключаем расширения RTL:

import "@testing-library/jest-dom";

Скрипт test:watch дает быстрый отклик при изменениях.

2. Тестируем синхронный рендер компонента

Компонент UserCard принимает пропсы и выводит имя. Тест проверяет появление текста.

import { render, screen } from "@testing-library/react";
import UserCard from "./UserCard";

test("отображает имя пользователя", () => {
  render(<UserCard name="Иван" />);
  expect(screen.getByText("Иван")).toBeInTheDocument();
});
  • Не используем container напрямую RTL советует искать элементы так, как их ищет пользователь.
  • toBeInTheDocument делает проверку читаемой.
  • Уточняйте типы пропсов в TypeScript, чтобы избежать ошибок в рантайме.

3. Асинхронные запросы и мок-сервер

Компоненты, делающие запросы к API, часто становятся источником багов. В 2025 году рекомендуется Mock Service Worker (MSW) он перехватывает запросы на уровне сети и не требует правок кода.

// src/mocks/handlers.ts
import { rest } from "msw";

export const handlers = [
  rest.get("/api/users", (req, res, ctx) => {
    return res(
      ctx.status(200),
      ctx.json([
        { id: 1, name: "Алиса" },
        { id: 2, name: "Боб" },
      ])
    );
  }),
];

Запуск MSW в тестах:

// src/setupTests.ts
import { server } from "./mocks/server";

beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());

Тестируем компонент UserList:

import { render, screen, waitFor } from "@testing-library/react";
import UserList from "./UserList";

test("загружает и отображает список пользователей", async () => {
  render(<UserList />);
  expect(screen.getByText("Загрузка…")).toBeInTheDocument();

  await waitFor(() => expect(screen.getByText("Алиса")).toBeInTheDocument());
  expect(screen.getByText("Боб")).toBeInTheDocument();
});

4. Снимки состояния (snapshot) когда они уместны

Snapshot-тесты подходят только для “статических” компонентов без бизнес-логики.

import { render } from "@testing-library/react";
import Header from "./Header";

test("snapshot Header", () => {
  const { asFragment } = render(<Header title="Главная" />);
  expect(asFragment()).toMatchSnapshot();
});

Новые рекомендации 2025: с версии @testing-library/jest-dom v6 рекомендуется задавать опцию ignoreAttributes: ['style'] в toMatchSnapshot, чтобы избегать лишних срабатываний при изменении стилистики.

Плюсы: быстрый способ убедиться, что разметка не изменилась без намерения. Минусы: ложные срабатывания при изменении небольших атрибутов. Храните такие тесты в папке __snapshots__ и запускать их периодически, а не на каждом CI-билде.

5. Таблица типичных ошибок и способы их устранения

ОшибкаПочему происходитКак исправить
Тест падает из-за тайм-аутовАсинхронный запрос не завершенДобавьте await waitFor или используйте findBy*
Мок-сервер не перехватывает запросНеправильный путь в rest.getПроверьте URL, используйте * для wildcard
Снимки постоянно меняютсяПереход на новую версию UI-библиотекиПересмотрите необходимость snapshot-теста
Тесты зависят от глобального состоянияНе очищаете localStorage/sessionStorageДобавьте cleanup в afterEach
Ожидание null вместо undefinedНеправильный тип пропсаЯвно указывайте типы в TypeScript

Эти подсказки помогут держать unit-тесты в React чистыми и быстрыми.

FAQ / чеклист

  1. Не путайте unit-тесты с e2e проверяйте лишь один компонент, а не весь пользовательский путь.
  2. Отдавайте предпочтение findBy* вместо waitFor, когда ждете появления элемента в DOM.
  3. Храните мок-данные рядом с тестом, чтобы они не “засоряли” продакшн-код.
  4. Не пишите тесты на стили проверяйте только семантику (текст, роли, атрибуты).
  5. Регулярно обновляйте snapshots, но только после осознанного ревью изменений.

Unit-тесты в React остаются важным инструментом, позволяющим быстро обнаружить регрессии и поддерживать качество кода без лишних хлопот.

Готов начать?

Выбери удобный способ связи — напиши напрямую или оставь заявку

Написать в Telegram

Отвечу в течение пары часов