Как неглубоко протестировать связанный компонент без редукции, который использует перехватчики редукции
У меня возникла проблема с моими модульными тестами в jest/ ferme в моем проекте ReactJS, я преобразовал свои компоненты в ES6 и использовал хуки для подключения redux к хранилищу редукторов. Однако после добавления изменения в использование хуков в этом компоненте модульный тест для него был сломан, и я потратил несколько дней, пытаясь выяснить, почему этот тест больше не будет неглубоким рендером, поскольку полное монтирование будет работать нормально.
DemoPage.js
import React from 'react';
import { useSelector, useDispatch} from 'react-redux';
import * as actions from '../../actions/demoPageActions';
import DemoPageForm from '../demoApp/DemoPageForm';
import {compose} from "recompose";
import {withStyles} from "@material-ui/core";
const styles = theme => ({});
export const DemoPage = () => {
const demoState = useSelector(state => state.demoPage);
const dispatch = useDispatch();
const saveSomething = () => {
dispatch(actions.saveSomething(demoState));
};
const calculateSomething = e => {
dispatch(actions.calculateSomething(demoState, e.target.name, e.target.value));
};
return (
<DemoPageForm
onSaveClick={saveSomething}
onChange={calculateSomething}
demoState={demoState}
/>
);
};
export default compose(withStyles(styles))(DemoPage);
DemoPage.spec.js
import React from "react";
import { shallow } from "enzyme";
import {DemoPage} from "./DemoPage";
import DemoPageForm from "../demoApp/DemoPageForm";
describe("<DemoPage />", () => {
it("should contain <DemoPageForm />", () => {
const wrapper = shallow(
<DemoPage/>
);
expect(wrapper.find(DemoPageForm).length).toEqual(1);
});
});
Что вызывает следующую ошибку
<DemoPage /> › should contain <DemoPageForm />
Invariant Violation: could not find react-redux context value; please ensure the component is wrapped in a <Provider>
9 |
10 | export const DemoPage = () => {
> 11 | const demoState = useSelector(state => state.demoPage);
| ^
12 | const dispatch = useDispatch();
13 |
14 | const saveSomething = () => {
Это очень сбивает с толку, так как он все еще должен тестировать неподключенный компонент, однако я считаю, что крючки для useSelector вызывают эту проблему, поэтому, прочитав около 30-40 страниц контента об этом, я еще не нашел решения и ближайшего, что у меня есть использует монтирование, которое отлично работает, но я бы предпочел мелкую для этого тестирования, вот код и результат, завернутый в провайдер с mockstore
describe("<DemoPage />", () => {
const mockStore = configureMockStore()
const store = mockStore(returnInitialState());
it("should contain <DemoPageForm />", () => {
const wrapper = shallow(
<Provider store={store}>
<DemoPage
store={store}
/>
</Provider>
);
console.log(wrapper.dive().debug())
expect(wrapper.find(DemoPageForm).length).toEqual(1);
});
});
console.log src/components/containers/DemoPage.spec.js:23
<DemoPage store={{...}} />
● <DemoPage /> › should contain <DemoPageForm />
expect(received).toEqual(expected) // deep equality
Expected: 1
Received: 0
23 | console.log(wrapper.dive().debug())
24 |
> 25 | expect(wrapper.find(DemoPageForm).length).toEqual(1);
| ^
26 | });
27 | });
Если кто-нибудь знает, как это можно решить, это было бы чрезвычайно полезно. Ура
2 ответа
У меня были проблемы с работой с shallow
рендеринг с ферментом. В настоящее время фермент не поддерживает полностью реагирующие крючки в тестовых компонентах с мелкой визуализацией. На данный момент вам нужно будет использовать маунт. Вы можете отслеживать прогресс на странице проблемы, привязанной к их github в проблеме #1938.
Если вы хотите попробовать использовать shallow, в настоящее время у вас есть доступ к немалому количеству функций. Попробуйте обновитьenzyme-adapter-react-16
к версии 1.15.1
или новее, чтобы устранить некоторые наиболее очевидные проблемы. У него определенно все еще есть проблемы с 11/12/19, когда я последний раз пытался добавить его, но все время становится лучше, поскольку они работают над проблемами совместимости.
Ваш тест не проходит именно потому, что shallow
просто отображает один уровень дерева DOM. Таким образом, вы получаете только<Provider />
часть дерева никогда не достигает <DemoPage />
. Это также объясняет, почемуmount
работает отлично.
Вам, вероятно, следует более внимательно прочитать doc™️, прежде чем переходить в режим безумия в Google. Обратите внимание, чтоshallow(node, options)
функция принимает второй аргумент. И там он предоставляет два способа взаимодействия с React Context:
- вы либо передаете объект Context в
options.context
прямо - или вы можете передать компонент поставщика, несущий этот контекст, в
options.wrappingComponent
.
Пример кода для options.wrappingComponent
Применение:
import { Provider } from 'react-redux';
import { Router } from 'react-router';
import store from './my/app/store';
import mockStore from './my/app/mockStore';
function MyProvider(props) {
const { children, customStore } = props;
return (
<Provider store={customStore || store}>
<Router>
{children}
</Router>
</Provider>
);
}
MyProvider.propTypes = {
children: PropTypes.node,
customStore: PropTypes.shape({}),
};
MyProvider.defaultProps = {
children: null,
customStore: null,
};
const wrapper = shallow(<MyComponent />, {
wrappingComponent: MyProvider,
});
const provider = wrapper.getWrappingComponent();
provider.setProps({ customStore: mockStore });
Отказ от ответственности: приведенный выше код беззастенчиво копируется прямо из ссылки на ферментную документацию здесь.