В React Testing Library (RTL) основное внимание уделяется
тестированию компонентов, имитируя поведение пользователей. Однако в
процессе тестирования часто возникает необходимость в создании
собственных методов рендеринга для компонентов, чтобы упростить тесты,
сделать их более читаемыми и повторно использовать общие настройки. В
таких случаях полезным инструментом становится создание функции
custom render, которая позволяет добавлять дополнительную
функциональность, такую как обёртки контекста или настройки для Redux, и
упростить работу с компонентами в тестах.
Реализация custom render позволяет решать несколько задач одновременно:
Таким образом, custom render облегчает работу, особенно когда нужно работать с более сложными компонентами, требующими окружения для тестирования.
Функция custom render является простым расширением
стандартной функции render из React Testing Library. Она
принимает два основных аргумента:
Вот пример реализации простой custom render-функции:
import { render } from '@testing-library/react';
import { MyContextProvider } from './MyContext';
const customRender = (ui, options = {}) =>
render(ui, { wrapper: MyContextProvider, ...options });
В этом примере мы оборачиваем компонент в провайдер контекста
MyContextProvider. Это полезно, если компоненты требуют
контекста для корректной работы. Важно, что в custom render можно
передать дополнительные параметры (например, для настройки
render), используя оператор распространения.
Когда приложение использует Context API для управления состоянием, важно тестировать компоненты, которые потребляют этот контекст. Если каждый тест будет требовать повторного использования одного и того же провайдера контекста, можно инкапсулировать эту логику в custom render.
Пример использования custom render с контекстом:
import { render, screen } from '@testing-library/react';
import { UserContextProvider } from './UserContext';
import UserProfile from './UserProfile';
const customRender = (ui, options = {}) =>
render(ui, { wrapper: UserContextProvider, ...options });
test('проверка компонента UserProfile', () => {
customRender(<UserProfile />);
// Здесь тестируем, что компонент правильно отображает информацию о пользователе.
expect(screen.getByText('Имя пользователя')).toBeInTheDocument();
});
В данном примере контекст пользователя предоставляется через
UserContextProvider. Это позволяет всем тестируемым
компонентам, использующим этот контекст, автоматически иметь доступ к
состоянию пользователя.
Если приложение использует Redux для управления состоянием, custom
render может быть полезен для автоматического обёртывания компонента в
нужный Provider из react-redux. Это позволяет
эффективно протестировать компоненты, подключенные к
Redux-хранилищу.
Пример custom render с Redux:
import { render } from '@testing-library/react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducer from './reducers';
import MyComponent from './MyComponent';
const customRender = (ui, { initialState, store = createStore(rootReducer, initialState), ...options } = {}) =>
render(ui, {
wrapper: ({ children }) => <Provider store={store}>{children}</Provider>,
...options,
});
test('проверка компонента с Redux', () => {
const initialState = { user: { name: 'Иван' } };
customRender(<MyComponent />, { initialState });
expect(screen.getByText('Иван')).toBeInTheDocument();
});
В этом примере создаётся хранилище Redux с исходным состоянием и
передаётся через Provider. Такой подход позволяет
тестировать компоненты, которые подключены к Redux, без необходимости в
дополнительных настройках или повторном создании хранилища.
Когда приложение использует сторонние библиотеки, такие как
react-router-dom, подключение маршрутизации также можно
инкапсулировать в custom render. Это удобно для тестирования
компонентов, которые используют роутинг.
Пример custom render с роутером:
import { render } from '@testing-library/react';
import { BrowserRouter } from 'react-router-dom';
import MyComponent from './MyComponent';
const customRender = (ui, options = {}) =>
render(ui, { wrapper: BrowserRouter, ...options });
test('проверка компонента с маршрутом', () => {
customRender(<MyComponent />);
expect(screen.getByText('Добро пожаловать на главную страницу')).toBeInTheDocument();
});
Здесь BrowserRouter предоставляет контекст для
компонентов, использующих роутинг, и гарантирует, что тестируемый
компонент будет работать так же, как в реальном приложении.
Custom render может быть полезен в случае, когда необходимо протестировать компонент с разными конфигурациями. Например, можно создать несколько вариантов initialState для Redux или передать различные значения в провайдеры контекста. Это даёт возможность протестировать один и тот же компонент в различных условиях, что повышает точность тестов.
Пример тестирования с разными конфигурациями:
test('тест с разными значениями контекста', () => {
customRender(<UserProfile />, { initialState: { user: { name: 'Иван' } } });
expect(screen.getByText('Иван')).toBeInTheDocument();
customRender(<UserProfile />, { initialState: { user: { name: 'Мария' } } });
expect(screen.getByText('Мария')).toBeInTheDocument();
});
Этот подход позволяет убедиться, что компонент корректно работает в различных состояниях контекста, не повторяя код.
Использование custom render в тестах с React Testing Library является важным шагом к улучшению структуры тестов, облегчая их поддержку и снижая дублирование кода. Этот подход позволяет инкапсулировать логику работы с контекстами, Redux, роутингом и другими сторонними библиотеками в единую функцию, что делает тестирование компонентов более чистым и удобным.