Тестирование вложенных компонентов с ферментом внутри React & Redux
у меня есть компонент SampleComponent
который монтирует другой " подключенный компонент "(т. е. container
). Когда я пытаюсь проверить SampleComponent
by mount
ing (так как мне нужно componentDidMount
), Я получаю ошибку:
инвариантное нарушение: не удалось найти "хранилище" ни в контексте, ни реквизит "Connect(ContainerComponent)". Либо оберните корневой компонент в a или явно передать "store" в качестве опоры для "Connect (ContainerComponent)".
каков наилучший способ тестирования это?
5 ответов
держатель энзима принимает опционные параметры. Два, которые необходимы для того, что вам нужно
options.context: (Object [optional]): Context to be passed into the component
options.childContextTypes: (Object [optional]): Merged contextTypes for all children of the wrapper
Ты бы сел на лошадь!--3--> С объектом options, как так:
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
.
то, что я по существу сделал, было принести в мой redux
магазин (и 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);
});
1)
вы можете обернуть компонент контейнера компонентом поставщика React-Redux в рамках вашего теста. Таким образом, при таком подходе вы фактически ссылаетесь на хранилище, передаете его поставщику и составляете тестируемый компонент внутри. Преимущество этого подхода заключается в том, что вы можете создать собственное хранилище для теста. Этот подход полезен, если вы хотите проверить вместе, связанные компоненты компонентов.
2)может быть, вы не забота о тестировании частей, связанных с Redux. Если вы просто заинтересованы в тестировании рендеринга компонента и поведения, связанного с локальным состоянием, вы можете просто добавить именованный экспорт для несвязанной простой версии вашего компонента. И просто чтобы уточнить, когда вы добавляете ключевое слово "export" в свой класс, вы говорите, что теперь класс может быть импортирован двумя способами либо с фигурными скобками {}, либо нет. пример:
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.
надеюсь, кто-нибудь там поможет.
вы можете использовать экспорт имен для решения этой проблемы:
вы должны:
class SampleComponent extends React.Component{
...
render(){
<div></div>
}
}
export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent)
вы можете добавить экспорт до класс:
export class SampleComponent extends React.Component{
и импортировать этот компонент без redux store:
import { SampleComponent } from 'your-path/SampleComponent';
С помощью этого решения вам не нужно импортировать хранилище в тестовые файлы.
в попытке сделать использование синтаксиса декоратора более проверяемым, я сделал это: https://www.npmjs.com/package/babel-plugin-undecorate
вход:
@anyOldClassDecorator
export class AnyOldClass {
@anyOldMethodDecorator
method() {
console.log('hello');
}
}
выход:
@anyOldClassDecorator
export class AnyOldClass {
@anyOldMethodDecorator
method() {
console.log('hello');
}
}
export class __undecorated__AnyOldClass {
method() {
console.log('hello');
}
}
надеюсь, это может стать прочной 3!