使用enzyme.mount()。setProps和react-redux Provider

时间:2017-02-28 12:06:38

标签: reactjs testing redux react-redux

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

我通过

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

然后我尝试使用以下内容来观察一些更改:

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

问题是setProps()没有在包装组件上正确设置道具。我认为这是因为<Provider>实际上没有通过道具,因为它不是HoC。有没有更好的方法来测试这个,而不仅仅是更改本地范围的道具变量和重新渲染?

4 个答案:

答案 0 :(得分:0)

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

一个好的经验法则是你的测试应该只测试一个组件(父组件),所以不允许用酶设置儿童道具。

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

如果您的子组件进一步向下,我们需要满足(通过Provider和context)的商店依赖关系,那么这很好,但这些子组件应该有自己独立的测试。

这是鼓励您为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)
})

另一个提示是,它有助于理解浅和mount之间的区别,因此您不必在测试中不必要地模仿儿童的依赖关系,这里的最佳答案是一个很好的阅读:

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

答案 1 :(得分:0)

这是使用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);
})

答案 2 :(得分:0)

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

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

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

但是在测试本身中,我做到了:

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

答案 3 :(得分:0)

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

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

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<any> | ReactText。由于我们确定Provider中呈现的元素是ReactElement,因此最快的解决方案是使用类型断言。