Enzyme — это мощный инструмент для тестирования компонентов React,
который предоставляет средства для удобной манипуляции компонентами,
симуляции событий и проверки состояний. Однако в процессе тестирования
часто возникает необходимость использовать контексты, которые зависят от
внешних провайдеров, таких как Redux Provider,
React Router или собственные контексты React. Для таких
случаев в Enzyme предусмотрен механизм обёртывания компонента в нужные
провайдеры с помощью утилиты Provider и других
вспомогательных компонентов.
При тестировании компонентов, использующих контекст (например, через
React Context или сторонние библиотеки, такие как Redux),
важно, чтобы компонент был правильно обёрнут в нужный провайдер, который
передает данные в дерево компонентов. Без правильного обёртывания
контекст не будет работать, и тесты не смогут воспроизвести поведение
компонента в реальном приложении. Для этого Enzyme предоставляет способы
оборачивания тестируемого компонента в необходимый контекст с помощью
специального инструмента — обёртки через mount или
shallow.
mount и shallowВ Enzyme можно использовать два подхода к рендерингу компонентов:
mount и shallow. Каждый из них может
потребовать различного подхода для обёртывания компонента в провайдер, в
зависимости от того, какой уровень тестирования необходим.
mount — полный рендеринг компонента с
учётом всего дерева компонентов, включая вложенные контексты.shallow — рендерит только сам
компонент, без его дочерних компонентов, что делает этот метод более
быстрым, но ограничивает функциональность.Для обоих подходов может потребоваться передача контекста через обёртывание компонента. Рассмотрим оба подхода.
mountmount рендерит компонент и его детей полностью, создавая
реальную иерархию компонентов с реальными контекстами и провайдерами.
Это удобный способ для тестирования компонентов, использующих такие
библиотеки, как Redux или React Router,
которые полагаются на провайдеры для передачи данных.
Пример обёртывания компонента с использованием Provider
из react-redux:
import { mount } from 'enzyme';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import MyComponent from './MyComponent';
const store = createStore(() => ({ user: { name: 'John' } }));
const wrapper = mount(
<Provider store={store}>
<MyComponent />
</Provider>
);
it('renders user name from Redux store', () => {
expect(wrapper.find('p').text()).toBe('John');
});
В этом примере создается хранилище Redux с данными о пользователе,
которое передается через Provider в компонент
MyComponent. В тесте проверяется, что компонент отображает
имя пользователя, извлечённое из состояния Redux.
shallowshallow рендерит только сам компонент без его детей, что
делает его подходящим для тестирования без необходимости рендерить всю
иерархию. Однако, если компонент зависит от контекста, обёртывание в
нужный провайдер всё равно может понадобиться.
Пример использования shallow с обёртыванием:
import { shallow } from 'enzyme';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import MyComponent from './MyComponent';
const store = createStore(() => ({ user: { name: 'John' } }));
const wrapper = shallow(
<Provider store={store}>
<MyComponent />
</Provider>
);
it('does not render user name directly', () => {
expect(wrapper.find('p').length).toBe(0); // С shallow не будет найдено элемента, так как компонент не рендерит детей
});
Здесь shallow используется для тестирования только
самого компонента, не рендеря его дочерние компоненты. Это может быть
полезно для тестирования взаимодействия компонента с контекстом, без
необходимости рендерить всё дерево.
В случае, если компонент использует собственный контекст, например,
созданный через React.createContext(), можно использовать
Context.Provider для передачи значений в тестируемый
компонент.
Пример для тестирования компонента, использующего собственный контекст:
import { mount } from 'enzyme';
import React, { createContext, useContext } from 'react';
const UserContext = createContext();
const MyComponent = () => {
const user = useContext(UserContext);
return <p>{user.name}</p>;
};
const wrapper = mount(
<UserContext.Provider value={{ name: 'John' }}>
<MyComponent />
</UserContext.Provider>
);
it('renders user name from context', () => {
expect(wrapper.find('p').text()).toBe('John');
});
В этом примере используется UserContext.Provider для
передачи значения в компонент MyComponent. Тест проверяет,
что компонент правильно извлекает значение из контекста и отображает
его.
Рендеринг контекста: Прежде чем тестировать компонент, важно правильно обернуть его в необходимые провайдеры. Это особенно важно для сложных приложений, использующих Redux, React Router, или собственные контексты.
mount vs shallow: При
использовании mount компонент рендерится полностью, включая
дочерние компоненты, и контексты передаются корректно. В случае с
shallow необходимо помнить, что контексты могут не работать
так, как в реальном приложении, поскольку дочерние компоненты не
рендерятся.
Провайдеры сторонних библиотек: Для таких
библиотек, как Redux или React Router,
необходимо оборачивать компонент в соответствующие провайдеры. В случае
с Redux — это Provider, а с
React Router — это MemoryRouter или
BrowserRouter, в зависимости от типа тестирования.
Тестирование поведения: При тестировании компонентов, использующих контекст, важно не только проверять, отображается ли правильное значение, но и тестировать логику взаимодействия с контекстом (например, действия в Redux или маршрутизация в React Router).
Правильное обёртывание компонентов в провайдеры является неотъемлемой
частью эффективного тестирования с использованием Enzyme. Это позволяет
точно имитировать поведение компонентов в реальных приложениях, где
контексты и провайдеры играют важную роль. Выбор между
mount и shallow зависит от цели тестирования,
но важно всегда помнить, что корректная передача контекста — это ключ к
успешным тестам.