使用React&Redux内部酶进行测试的嵌套组件

问题描述:

我有一个组件SampleComponent,它安装了另一个“连接组件”(即container)。当我尝试通过mount ING测试SampleComponent(因为我需要的componentDidMount),我得到的错误:使用React&Redux内部酶进行测试的嵌套组件

Invariant Violation: Could not find "store" in either the context or props of "Connect(ContainerComponent)". Either wrap the root component in a , or explicitly pass "store" as a prop to "Connect(ContainerComponent)".

什么是测试这个的最佳方式?

我基本上没在我的redux存储(和Provider)带来,并把它包在一个工具组件,如下所示:

export const CustomProvider = ({ children }) => { 
    return (
    <Provider store={store}> 
     {children} 
    </Provider> 
); 
}; 

然后,我mountSampleComponent和运行测试反对:

it('contains <ChildComponent/> Component',() => { 
    const wrapper = mount(
    <CustomProvider> 
     <SampleComponent {...defaultProps} /> 
    </CustomProvider> 
); 
    expect(wrapper.find(ChildComponent)).to.have.length(1); 
}); 
+0

我看到你正在使用mount,如果我尝试用''shallo''替换''mount''出现错误。你也遇到过吗? – Mehrdad

+2

虽然此答案在某些情况下有效,但在需要测试组件的生命周期时不起作用。例如,调用'wrapper.setProps()'不会触发'SampleComponent'上的'componentWillReceiveProps()'。 –

酶的安装需要可选参数。两所必需的,你需要的是

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将通过您所提供到上下文。

+2

这是完美的!尽管接受的答案在大多数情况下都适用,但缺点是您无法使用安装API来发挥最大能力。例如,使用“提供者”包装组件的接受答案不允许使用'wrapper.state()'api。该解决方案将为您提供包装的全套方法。 – neurosnap

+0

由于上述原因(即,您的挂载包装实际上不是您正在尝试测试的组件),这比接受的答案更好,也因为您可以使用模拟商店而不是实际商店,所有这些都减少了。 – GTF

+2

此可选参数不在文档中,您是如何找到它的?在代码中? –

您可以使用名称出口来解决这个问题:

你应该有:

class SampleComponent extends React.Component{ 
... 
    render(){ 
     <div></div> 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent) 

您可以在课前添加一个出口:

export class SampleComponent extends React.Component{ 

,并没有导入该组件REDO商店:

import { SampleComponent } from 'your-path/SampleComponent'; 

使用此解决方案,您无需将商店导入到测试文件中。

选项1)您可以在测试中使用React-Redux的Provider组件包装容器组件。因此,采用这种方法,您实际上会引用商店,将其传递给提供商,并在测试中组成您的组件。这种方法的优点是您可以为测试创建一个自定义商店。如果要测试组件的与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. 

我希望可以帮助那里的人。