Вложенные компоненты, испытывающие фермент внутри React & Redux
У меня есть компонент SampleComponent
, который монтирует другой "подключенный компонент" (т.е. container
). Когда я пытаюсь проверить SampleComponent
на mount
ing (так как мне нужен componentDidMount
), я получаю ошибку:
Инвариантное нарушение: не удалось найти "хранилище" в контексте или реквизиты "Connect (ContainerComponent)". Либо оберните корневой компонент в или явно передать "store" в качестве опоры для "Connect (ContainerComponent)".
Какой лучший способ проверить это?
Ответы
Ответ 1
В основном я сделал вывод в мой redux
store (и Provider
) и завернул его в компонент утилиты следующим образом:
export const CustomProvider = ({ children }) => {
return (
<Provider store={store}>
{children}
</Provider>
);
};
тогда я mount
SampleComponent
и выполните тесты против него:
it('contains <ChildComponent/> Component', () => {
const wrapper = mount(
<CustomProvider>
<SampleComponent {...defaultProps} />
</CustomProvider>
);
expect(wrapper.find(ChildComponent)).to.have.length(1);
});
Ответ 2
Ферментное крепление принимает необязательные параметры. Эти два, которые необходимы для того, что вам нужно,
options.context: (Object [optional]): Context to be passed into the component
options.childContextTypes: (Object [optional]): Merged contextTypes for all children of the wrapper
Вы бы установили SampleComponent
с таким образом:
const store = {
subscribe: () => {},
dispatch: () => {},
getState: () => ({ ... whatever state you need to pass in ... })
}
const options = {
context: { store },
childContextTypes: { store: React.PropTypes.object.isRequired }
}
const _wrapper = mount(<SampleComponent {...defaultProps} />, options)
Теперь ваш SampleComponent передаст контекст, который вы предоставили, до connected component
.
Ответ 3
Вы можете использовать экспорт имен для решения этой проблемы:
Вы должны иметь:
class SampleComponent extends React.Component{
...
render(){
<div></div>
}
}
export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent)
Вы можете добавить экспорт перед классом:
export class SampleComponent extends React.Component{
и импортируйте этот компонент без хранилища redux:
import { SampleComponent } from 'your-path/SampleComponent';
С помощью этого решения вам не нужно импортировать хранилище в тестовые файлы.
Ответ 4
Вариант 1). Вы можете обернуть компонент контейнера компонентом поставщика React-Redux в своем тесте. Таким образом, при таком подходе вы фактически обращаетесь в магазин, передаете его Поставщику и составляете свой компонент под тестом внутри. Преимущество такого подхода заключается в том, что вы можете создать собственный магазин для теста. Этот подход полезен, если вы хотите протестировать связанные с Redux части вашего компонента.
Вариант 2) Возможно, вам не нужно тестировать части, связанные с Redux. Если вам просто интересно тестировать рендеринг компонентов и поведение, связанное с локальным состоянием, вы можете просто добавить именованный экспорт для несвязанной простой версии вашего компонента. И просто чтобы уточнить, когда вы добавляете ключевое слово "экспорт" в свой класс, в основном вы говорите, что теперь класс может быть импортирован двумя способами либо с фигурными фигурными скобками {}, либо нет. Пример:
export class MyComponent extends React.Component{ render(){ ... }}
...
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
позже в тестовом файле:
import MyComponent from 'your-path/MyComponent'; // it needs a store because you use "default export" with connect
import {MyComponent} from 'your-path/MyComponent'; // don't need store because you use "export" on top of your class.
Я надеюсь, что кто-то там поможет.