Nested components testing with Enzyme inside of React & Redux Nested components testing with Enzyme inside of React & Redux reactjs reactjs

Nested components testing with Enzyme inside of React & Redux


Enzyme's mount takes optional parameters. The two that are necessary for what you need are

options.context: (Object [optional]): Context to be passed into the component

options.childContextTypes: (Object [optional]): Merged contextTypes for all children of the wrapperYou would mount SampleComponent with an options object like so:

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)

Now your SampleComponent will pass the context you provided down to the connected component.


What I essentially did was bring in my redux store (and Provider) and wrapped it in a utility component as follows:

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

then, I mount the SampleComponent and run tests against it:

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


Option 1)

You can wrap the container component with React-Redux's Provider component within your test. So with this approach, you actually reference the store, pass it to the Provider, and compose your component under test inside. The advantage of this approach is you can actually create a custom store for the test. This approach is useful if you want to test the Redux-related portions of your component.

Option 2)

Maybe you don't care about testing the Redux-related pieces. If you're merely interested in testing the component's rendering and local state-related behaviors, you can simply add a named export for the unconnected plain version of your component. And just to clarify when you add the "export" keyword to your class basically you are saying that now the class could be imported in 2 ways either with curly braces {} or not. example:

export class MyComponent extends React.Component{ render(){ ... }}...export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)

later on your test file:

import MyComponent from 'your-path/MyComponent'; // it needs a store because you use "default export" with connectimport {MyComponent} from 'your-path/MyComponent'; // don't need store because you use "export" on top of your class.

I hope helps anyone out there.