Напишите эффективные и надежные тесты для ваших приложений React, используя Jest

Тестирование — важнейший аспект разработки программного обеспечения, который помогает нам гарантировать надежность, удобство сопровождения и эффективность нашего кода. React, одна из самых популярных библиотек JavaScript для создания пользовательских интерфейсов, имеет динамичную экосистему с множеством инструментов и библиотек, помогающих в написании тестов. Jest — одна из таких сред тестирования, которая в последние годы приобрела огромную популярность.

Jest, разработанный Facebook, представляет собой мощную и гибкую среду тестирования, которая позволяет разработчикам писать тесты как для простых, так и для сложных компонентов React. В этой статье мы рассмотрим, как вы можете протестировать свои компоненты React с помощью Jest, а также поделимся практическими примерами кода, которые помогут вам сразу приступить к работе.

Настройка Jest в вашем проекте React

Чтобы начать работу с Jest, вам сначала нужно установить его и настроить в своем проекте React. Вы можете сделать это, выполнив следующую команду:

npm install — save-dev jest babel-jest @babel/preset-env @babel/preset-react react-test-renderer

Затем создайте файл .babelrc в корне вашего проекта и добавьте следующую конфигурацию:

{
 "presets": ["@babel/preset-env", "@babel/preset-react"]
}

Наконец, добавьте следующий тестовый скрипт в ваш package.json:

{
  "scripts": {
    "test": "jest"
  }
}

Теперь вы готовы начать писать тесты для своих компонентов React!

Начнем с тестирования простого компонента React. Рассмотрим следующий компонент «Счетчик», который позволяет пользователям увеличивать и уменьшать значение:

import React, { useState } from 'react';

export const Counter = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
    </div>
  );
};

Чтобы протестировать этот компонент, мы создадим файл Counter.test.js вместе с файлом компонента и напишем следующий тест:

import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import { Counter } from './Counter';

test('Counter increments and decrements count', () => {
  const { getByText } = render(<Counter />);
  const countElement = getByText(/count:/i);
  const incrementButton = getByText(/increment/i);
  const decrementButton = getByText(/decrement/i);

  expect(countElement.textContent).toBe('Count: 0');

  fireEvent.click(incrementButton);
  expect(countElement.textContent).toBe('Count: 1');

  fireEvent.click(decrementButton);
  expect(countElement.textContent).toBe('Count: 0');
});

В этом тесте мы используем библиотеку @testing-library/react для рендеринга компонента Счетчик и взаимодействия с его элементами. Сначала мы проверяем, равен ли начальный счетчик 0, затем моделируем событие щелчка на кнопках увеличения и уменьшения и подтверждаем, изменяется ли счетчик, как ожидалось.

Тестирование компонента с реквизитами

Теперь давайте протестируем компонент React, который получает свойства. Рассмотрим следующий компонент «Приветствие»:

import React from 'react';

export const Greeting = ({ name }) => {
  return <p>Hello, {name}!</p>;
};

Чтобы протестировать этот компонент, мы создадим файл `Greeting.test.js` и напишем следующий тест:

import React from 'react';
import { render } from '@testing-library/react';
import { Greeting } from './Greeting';

test('Greeting renders the correct text with given name', () => {
  const { getByText } = render(<Greeting name="John" />);
  expect(getByText(/hello, john!/i)).toBeInTheDocument();
});

В этом тесте мы визуализируем компонент «Приветствие» с реквизитом «имя» и утверждаем, что отображаемый текст включает предоставленное имя.

Тестирование компонента с состоянием и useEffect

Давайте протестируем более сложный компонент, использующий состояние и хук useEffect. Предположим, у нас есть компонент «Пользователь», который извлекает пользовательские данные из API и отображает их:

import React, { useState, useEffect } from 'react';

export const User = ({ userId }) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const fetchUser = async () => {
      const res = await fetch(`https://jsonplaceholder.typicode.com/users/${userId}`);
      const data = await res.json();
      setUser(data);
    };

    fetchUser();
  }, [userId]);

  return (
    <div>
      {user ? (
        <p>{user.name}</p>
      ) : (
        <p>Loading...</p>
      )}
    </div>
  );
};

Примечание. В этом примере мы используем API-заполнитель JSON — забавный, бесплатный и простой в использовании API для тестирования, разработки и обучения (https://jsonplaceholder.typicode.com/ )

Для этого компонента нам нужно смоделировать вызов API, чтобы обеспечить контролируемую среду тестирования. Мы создадим файл User.test.js и напишем следующий тест:

import React from 'react';
import { render, waitFor } from '@testing-library/react';
import { User } from './User';

// Mock API call
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve({ name: 'John Doe' }),
  }),
);

test('User component fetches and displays user data', async () => {
  const { getByText } = render(<User userId={1} />);

  expect(getByText(/loading.../i)).toBeInTheDocument();

  await waitFor(() => expect(getByText(/john doe/i)).toBeInTheDocument());

  expect(fetch).toHaveBeenCalledTimes(1);
});

В этом тесте мы имитируем функцию `fetch`, чтобы вернуть разрешенный промис с желаемым объектом пользователя. Затем мы визуализируем компонент Пользователь и проверяем, отображается ли загружаемый текст изначально. Используя функцию `waitFor` из `@testing-library/react`, мы ждем, пока пользовательские данные будут получены и отображены. Наконец, мы гарантируем, что функция `fetch` вызывается один раз.

Заключение

В этой статье мы рассмотрели, как тестировать компоненты React с помощью Jest, охватив различные сценарии, такие как тестирование компонентов с состоянием, реквизитами и useEffect. Следуя этим примерам, вы можете создавать надежные тесты для своих приложений React, гарантируя, что ваши компоненты ведут себя так, как ожидается, и упрощая поддержку и рефакторинг вашего кода в будущем.

Помните, что тестирование — это неотъемлемая часть разработки программного обеспечения, и затраты времени на изучение и внедрение правильных методов тестирования окупятся в долгосрочной перспективе. Удачного тестирования!