Как тестировать React-компоненты с помощью Jest и React Testing Library?

Ответ

Для unit-тестирования React-компонентов используется связка Jest (тест-раннер) и React Testing Library (RTL) (утилиты для взаимодействия с компонентами).

Ключевая философия RTL — тестировать компоненты так, как их видит пользователь, фокусируясь на поведении, а не на деталях реализации.

Основные виды тестов:

  1. Тестирование рендеринга Проверяем, что компонент корректно отображается с нужным контентом.

    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();
    });
  2. Тестирование событий Имитируем действия пользователя (клик, ввод текста) и проверяем реакцию компонента.

    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);
    });
  3. Тестирование асинхронных операций Для компонентов, выполняющих 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).