В общем, использование хуков не должно сильно менять стратегию тестирования.Большая проблема здесь на самом деле не в ловушке, а в использовании контекста, который немного усложняет ситуацию.
Есть несколько способов сделать эту работу, но я нашел только один подход, который работает с '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']);
});
(Отказ от ответственности: это должно работать, но когда я проверяю его, я сталкиваюсь с ошибкой, которая, по моему мнению, является проблемой в моей настройке)
Мелкий рендеринг с Enzyme иПогружение
Как прокомментировал @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
Наконец, Hooks FAQ содержит пример тестирования хуков с 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");
});