Интеграционное тестирование с React Testing Library
Рендерьте компоненты в тестах, инициируйте события и проверяйте видимый результат, а не реализацию.
«Интеграционное тестирование с React Testing Library» — бесплатный урок React Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения React Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс React Academy содержит 4 уроков всего.
Что такое React Testing Library
React Testing Library (RTL) поощряет тестирование с точки зрения пользователя: отображайте компоненты, взаимодействуйте с ними так, как это делал бы пользователь, и проверяйте видимый результат, а не детали реализации.
Настройка
RTL входит в Create React App и шаблон React для Vite. Для ручной настройки установите @testing-library/react и @testing-library/jest-dom.
// package.json
// "@testing-library/react": "^14.0.0",
// "@testing-library/jest-dom": "^6.0.0"
// setupTests.ts
import '@testing-library/jest-dom';Рендеринг компонента
render() монтирует компонент в виртуальном DOM. Он возвращает функции запросов, ограниченные отображённым результатом.
import { render, screen } from '@testing-library/react';
import { Button } from './Button';
test('renders button label', () => {
render(<Button label="Submit" onClick={() => {}} />);
expect(screen.getByText('Submit')).toBeInTheDocument();
});Поиск элементов
Предпочитайте запросы в таком порядке: getByRole > getByLabelText > getByPlaceholderText > getByText. Запросы по роли учитывают семантику доступности.
// Best: query by role
const button = screen.getByRole('button', { name: /submit/i });
// Good: query by label (for form inputs)
const input = screen.getByLabelText('Email address');
// Acceptable: query by text
const heading = screen.getByText('Welcome');Генерация событий
Используйте userEvent из @testing-library/user-event как предпочтительный вариант или базовый fireEvent. userEvent имитирует реальные взаимодействия с браузером, включая получение и потерю фокуса.
import userEvent from '@testing-library/user-event';
test('types into input', async () => {
const user = userEvent.setup();
render(<SearchBar />);
const input = screen.getByRole('textbox');
await user.type(input, 'react');
expect(input).toHaveValue('react');
});Проверка отправки формы
Отобразите форму, заполните поля с помощью userEvent.type, нажмите кнопку отправки и проверьте результат: сообщение об успехе, переход или вызов колбэка.
test('submits the login form', async () => {
const onLogin = jest.fn();
const user = userEvent.setup();
render(<LoginForm onLogin={onLogin} />);
await user.type(screen.getByLabelText('Email'), 'test@example.com');
await user.type(screen.getByLabelText('Password'), 'password123');
await user.click(screen.getByRole('button', { name: /log in/i }));
expect(onLogin).toHaveBeenCalledWith({ email: 'test@example.com', password: 'password123' });
});Проверка видимости
Сопоставители jest-dom, такие как toBeInTheDocument(), toBeVisible() и toHaveValue(), делают проверки понятными.
expect(screen.getByText('Error: required')).toBeInTheDocument();
expect(screen.getByRole('dialog')).toBeVisible();
expect(screen.getByRole('textbox')).toHaveValue('hello');
expect(screen.queryByText('Loading...')).not.toBeInTheDocument();Проверка условного рендеринга
Используйте queryBy, который возвращает значение null при отсутствии элемента, чтобы проверить, что элемент не отображается. Используйте getBy, если ожидаете, что элемент присутствует.
test('shows error message when validation fails', async () => {
const user = userEvent.setup();
render(<SignUpForm />);
await user.click(screen.getByRole('button', { name: /submit/i }));
expect(screen.getByText('Email is required')).toBeInTheDocument();
});Обёртывание в провайдеры
Большинству компонентов нужен контекст или маршрутизатор. Оборачивайте их в провайдеры внутри вызова render или создайте собственный вспомогательный метод renderWithProviders.
function renderWithProviders(ui: React.ReactElement) {
return render(
<QueryClientProvider client={new QueryClient()}>
<MemoryRouter>
{ui}
</MemoryRouter>
</QueryClientProvider>
);
}
test('shows user data', () => {
renderWithProviders(<UserProfile />);
});Проверка изменений состояния
Взаимодействуйте с компонентом, затем проверьте, что новое состояние отражено в интерфейсе. RTL автоматически оборачивает большинство взаимодействий в act при использовании userEvent.
test('counter increments', async () => {
const user = userEvent.setup();
render(<Counter />);
expect(screen.getByText('Count: 0')).toBeInTheDocument();
await user.click(screen.getByRole('button', { name: /increment/i }));
expect(screen.getByText('Count: 1')).toBeInTheDocument();
});Вспомогательное средство отладки экрана
Вызовите screen.debug(), чтобы вывести текущий отображённый HTML в консоль. Это полезно, если запрос не сработал и Вам нужно увидеть фактически отображённое содержимое.
test('debugging a failing query', () => {
render(<MyComponent />);
screen.debug(); // prints rendered HTML
screen.getByRole('button', { name: /save/i }); // then inspect output
});Быстрая проверка
Какому запросу следует отдавать предпочтение при проверке кнопки в React Testing Library?
Повторение
RTL отображает компоненты и взаимодействует с ними с помощью запросов на основе ролей и userEvent. Оборачивайте компоненты в необходимые провайдеры, используйте сопоставители jest-dom для понятных проверок и предпочитайте queryBy при проверке отсутствия элемента.
Часто задаваемые вопросы
Урок «Интеграционное тестирование с React Testing Library» бесплатный?
Да — полный текст урока «Интеграционное тестирование с React Testing Library» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс React Academy, подпишись на CoddyKit PRO. Курс React Academy содержит 4 уроков всего.
Чему я научусь в уроке «Интеграционное тестирование с React Testing Library»?
Рендерьте компоненты в тестах, инициируйте события и проверяйте видимый результат, а не реализацию. Ты практикуешь React Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать React Academy?
Предыдущий опыт не требуется. React Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Интеграционное тестирование с React Testing Library»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке React Academy?
Да. Каждый урок React Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Интеграционное тестирование с React Testing Library
- Тестирование асинхронного интерфейса и вызовов API с MSW
- Начало работы с Playwright для React
- Сквозное тестирование форм и пользовательских сценариев