Ответ
Для unit-тестирования React-компонентов используется связка Jest (тест-раннер) и React Testing Library (RTL) (утилиты для взаимодействия с компонентами).
Ключевая философия RTL — тестировать компоненты так, как их видит пользователь, фокусируясь на поведении, а не на деталях реализации.
Основные виды тестов:
-
Тестирование рендеринга Проверяем, что компонент корректно отображается с нужным контентом.
import { render, screen } from '@testing-library/react'; import Button from './Button'; test('renders button with correct text', () => { render(<Button>Click Me</Button>); // Ищем элемент по его роли и тексту, как это сделал бы пользователь expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument(); }); -
Тестирование событий Имитируем действия пользователя (клик, ввод текста) и проверяем реакцию компонента.
import { render, screen, fireEvent } from '@testing-library/react'; test('calls onClick handler when clicked', () => { const handleClick = jest.fn(); // Создаем mock-функцию render(<Button onClick={handleClick}>Click Me</Button>); fireEvent.click(screen.getByText(/click me/i)); // Проверяем, что обработчик был вызван один раз expect(handleClick).toHaveBeenCalledTimes(1); }); -
Тестирование асинхронных операций Для компонентов, выполняющих API-запросы, используются
async/awaitи методыfindBy*для ожидания появления элементов.test('loads and displays user data', async () => { render(<UserComponent />); // findBy* возвращает Promise, который разрешится, когда элемент появится в DOM const userName = await screen.findByText('John Doe'); expect(userName).toBeInTheDocument(); });Для изоляции тестов от реального бэкенда API-запросы мокаются с помощью
jest.mockили библиотек вроде Mock Service Worker (MSW).
Ответ 18+ 🔞
Слушай, а вот эта вся тема с тестированием компонентов в Реакте — это вообще отдельный вид искусства, блядь. Люди думают: «О, накидал кнопок, всё работает, зачем тесты?». А потом приходит новый чувак, чихнет рядом с кодом, и всё разъёбывается к хуям собачьим. Так вот, чтобы такого не было, есть два главных героя: Jest и React Testing Library (RWT, блядь, RTL).
Фишка RTL в том, что ты не ковыряешься во внутренностях компонента, как какой-то хирург-извращенец. Ты тестируешь его так, как видит пользователь: что на экране появилось, куда можно тыкнуть, что после этого произойдёт. Всё, пиздец, просто и гениально.
На чём обычно ловят воробушков, то есть пишут тесты:
-
Просто рендеринг, ёпта Проверяем, что компонент вообще появился на свет божий и показывает то, что должен.
import { render, screen } from '@testing-library/react'; import Button from './Button'; test('renders button with correct text', () => { render(<Button>Click Me</Button>); // Ищем кнопку по её роли и тексту, как это сделал бы нормальный человек, а не робот expect(screen.getByRole('button', { name: /click me/i })).toBeInTheDocument(); });Если тут тест упадёт — значит, ты или кнопку криво написал, или уже совсем еблан.
-
Тестирование кликов и прочей активности Вот тут начинается магия. Нужно сымитировать, что пользователь что-то сделал, и проверить, отреагировал ли компонент.
import { render, screen, fireEvent } from '@testing-library/react'; test('calls onClick handler when clicked', () => { const handleClick = jest.fn(); // Создаём муляж функции, шпиона, короче render(<Button onClick={handleClick}>Click Me</Button>); // Симулируем клик, как будто палец пользователя дрогнул fireEvent.click(screen.getByText(/click me/i)); // А теперь проверяем, вызвалась ли наша функция-шпион ровно один раз expect(handleClick).toHaveBeenCalledTimes(1); });Если
handleClickне вызвался — значит, твоя кнопка просто красивая картинка, и её надо выкинуть в помойку. -
Асинхронщина, блядь, самая большая головная боль Когда компонент лезет за данными на сервер, а мы не хотим, чтобы тесты реально туда стучались. Иначе один тест будет работать, а потом сервер ляжет, и все твои тесты накроются медным тазом.
test('loads and displays user data', async () => { render(<UserComponent />); // Метод findBy* — он умный, ждёт, пока элемент появится. Как будто сидишь и пялишься в экран. const userName = await screen.findByText('John Doe'); expect(userName).toBeInTheDocument(); });А чтобы не дёргать реальный бэкенд, запросы мокают. Либо через
jest.mock, либо через специальные штуки вроде Mock Service Worker (MSW), которые перехватывают твои запросы и подсовывают фейковые ответы. Красота, в рот меня чих-пых!
Вот и вся наука. Не так страшен чёрт, как его малюют. Главное — начать, а потом уже сам от себя офигеешь, насколько проще жить, когда за спиной стоит армия тестов, которая не даёт тебе накосячить.