【问题标题】:using enzyme.mount().setProps with a react-redux Provider将酶.mount().setProps 与 react-redux Provider 一起使用
【发布时间】:2017-07-19 09:37:24
【问题描述】:

我有一个设置 props 的测试,以观察组件的一些变化。唯一的复杂之处是我将渲染的元素包装在 <Provider> 中,因为在树的下方还有一些连接的组件。

我正在通过渲染

const el = () => <MyComponent prop1={ prop1 } />;
const wrapper = mount(<Provider store={store}>{ el() }</Provider>);

然后我尝试使用以下方法观察一些变化:

wrapper.setProps({ /* new props */ });
// expect()s etc.

问题是setProps() 没有在包装的组件上正确设置道具。我认为这是因为 &lt;Provider&gt; 实际上并没有传递道具,因为它不是 HoC。除了更改本地范围的 prop 变量并重新渲染之外,还有更好的测试方法吗?

【问题讨论】:

  • 现在,我通过mount(el, { context, childContextTypes }) 传递上下文而不是用&lt;Provider&gt; 包装解决了问题(尽管不是问题)。
  • 我也有同样的问题。我希望看到您的解决方案使用 childContextTypes 为您工作。你介意分享代码吗?
  • 基本上你只需要在上下文中设置商店,例如使用redux-mock-store。即mount(el, { context: { store }, childContextTypes: { store: PropTypes.object.isRequired }});.
  • 非常感谢@GTF 的回复。后来,我能够使用 context 和 childContextTypes 在互联网上关注其他示例。和你现在描述的一样。太棒了!

标签: reactjs testing redux react-redux


【解决方案1】:

另一种方法是使用wrappingComponent

例如,假设这是您的提供者

const ExampleProvider = ({ children }) => (
      <Provider store={store}>
        {children}
      </Provider>
    );

然后初始化wrapper如下

wrapper = mount(<Component />, { wrappingComponent: ExampleProvider});

然后在测试用例中,你应该可以直接调用wrapper.setProps

【讨论】:

  • 这是将包装组件(例如 Redux Provider 或 React Router)添加到安装有酶的子组件的正确方法。谢谢!
【解决方案2】:

我想提供与上述类似的解决方案。

使用问题中定义的安装包装器,

const wrapper = mount(<Provider store={store}>{ el() }</Provider>);

然后,在测试本身上,您可以简单地克隆子组件,即Provider 中的子组件,然后调用setProps

it('should get do x and y', () => {  
  wrapper.setProps({
    children: cloneElement(wrapper.props().children as ReactElement, { ...props }),
  });

  // handle the rest below
});

如果您使用 JavaScript,则无需包含 as ReactElement 类型断言。

对于那些使用 TypeScript 的人,有必要将其声明为 ReactElement,因为 ReactChild 可能是 ReactElement&lt;any&gt; | ReactText 类型。由于我们确定在 Provider 中呈现的元素是 ReactElement,因此最快的解决方案是使用类型断言。

【讨论】:

    【解决方案3】:

    在将组件包装在 Provider 中后,我遇到了同样的问题。我所做的是,我在子组件上使用了 setProps 而不是组件本身。

    这是我在测试套件中的组件示例:

     let component, connectedComponent; 
     component = () => {
     store = configureMockStore()(myStore);  
     connectedComponent = mount(
         <Provider >
           <MyComponent store={store} params={{xyz: 123}} />
         </Provider>);};
    

    但在测试本身中,我是这样做的:

    connectedComponent.setProps({children: <MyComponent params={{}} />});
    

    【讨论】:

      【解决方案4】:

      这是一种使用setProps的方法

      import { Provider } from 'react-redux';
      
      
      const renderComponent = properties => mount(
        React.createElement(
          props => (
            <Provider store={store}>
              <IntlProvider locale="en" defaultLocale="en" messages={messages}>
            <Router>
              <MyComponent {...props} />
            </Router>
      
            </Provider>
          ),
          properties))
      

      然后在你的测试中

      it('should set some props', () => {
         const renderedComponent = renderComponent(props);
         renderedComponent.setProps({ /* some props */ } });
      
        expect(true).toBe(true);
      })
      

      【讨论】:

        【解决方案5】:

        您应该只在包装的组件或父组件上调用setProps

        一个好的经验法则是您的测试应该只测试单个组件(父组件),因此不允许使用酶为子组件设置道具。

        https://github.com/airbnb/enzyme/blob/master/docs/api/ShallowWrapper/setProps.md#setpropsnextprops--self

        如果您有子组件需要我们满足存储依赖项(通过 Provider 和上下文),那很好,但这些子组件确实应该有自己的独立测试。

        我们鼓励您为setProps 上的更改编写测试。

        如果您发现自己正在为容器或连接器编写测试,您真的只想验证子组件是否接收到正确的道具和/或状态。例如:

        import { createMockStore } from 'mocks'
        import { shallwo } from 'enzyme'
        // this component exports the redux connection
        import Container from '../container'
        
        const state = { foo: 'bar' }
        
        let wrapper
        let wrapped
        let store
        
        beforeEach(() => {
          store = createMockStore(state)
          wrapper = shallow(<Container store={store} />)
          wrapped = wrapper.find('MyChildComponent')
        })
        
        it('props.foo', () => {
          const expected = 'bar'
          const actual = wrapped.prop('foo')
          expect(expected).toEqual(actual)
        })
        

        另一个提示是,它有助于理解 shallow 和 mount 之间的区别,这样您就不会在测试中不必要地嘲笑孩子的依赖关系,这里的最佳答案是一个很好的阅读:

        When should you use render and shallow in Enzyme / React tests?

        【讨论】:

        • 这并没有回答问题,有时你想用mount进行测试。如果您使用的是 redux,您应该能够测试您的内部组件并测试它如何管理 prop 更改、未从 store 交付的 props。
        猜你喜欢
        • 2019-02-05
        • 2017-12-09
        • 2018-12-05
        • 2018-06-10
        • 1970-01-01
        • 1970-01-01
        • 2018-02-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多