Ответ 1
В общем, использование хуков не должно сильно менять стратегию тестирования. Большая проблема здесь на самом деле не крючок, а использование контекста, который немного усложняет ситуацию.
Есть несколько способов заставить это работать, но единственный подход, который я нашел, который работает с 'react-test-renderer/shallow'
состоит во введении ложного хука:
import ShallowRenderer from 'react-test-renderer/shallow';
let realUseContext;
let useContextMock;
// Setup mock
beforeEach(() => {
realUseContext = React.useContext;
useContextMock = React.useContext = jest.fn();
});
// Cleanup mock
afterEach(() => {
React.useContext = realUseContext;
});
test("mock hook", () => {
useContextMock.mockReturnValue("Test Value");
const element = new ShallowRenderer().render(
<MyComponent />
);
expect(element.props.children).toBe('Test Value');
});
Хотя это немного грязно и зависит от реализации, поэтому, если вы можете пойти на компромисс в использовании поверхностного рендерера, есть несколько других доступных вариантов:
Неглубокий рендер
Если вы не мелкий рендеринг, вы можете просто обернуть компонент в провайдер контекста, чтобы ввести нужное значение:
import TestRenderer from 'react-test-renderer';
test("non-shallow render", () => {
const element = new TestRenderer.create(
<NameContext.Provider value="Provided Value">
<MyComponent />
</NameContext.Provider>
);
expect(element.root.findByType("div").children).toEqual(['Provided Value']);
});
(Отказ от ответственности: это должно работать, но когда я проверяю это, я получаю сообщение об ошибке, которое я считаю проблемой в моей настройке)
Мелкий рендер с энзимом и погружением
Как прокомментировал @skyboyer, энзимный рендеринг с мелким рендерингом поддерживает .dive
что позволяет вам глубоко рендерить рендеринг компонента с неглубоким рендерингом:
import { shallow } from "./enzyme";
test("enzyme dive", () => {
const TestComponent = () => (
<NameContext.Provider value="Provided Value">
<MyComponent />
</NameContext.Provider>
);
const element = shallow(<TestComponent />);
expect(element.find(MyComponent).dive().text()).toBe("Provided Value");
});
Используйте ReactDOM
Наконец, в FAQ по ReactDOM
есть пример тестирования хуков с помощью ReactDOM
, который также работает. Естественно, использование ReactDOM
означает, что это также глубокий рендер, а не мелкий.
let container;
beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});
afterEach(() => {
document.body.removeChild(container);
container = null;
});
test("with ReactDOM", () => {
act(() => {
ReactDOM.render((
<NameContext.Provider value="Provided Value">
<MyComponent />
</NameContext.Provider>
), container);
});
expect(container.textContent).toBe("Provided Value");
});