简体   繁体   中英

How to test a component with a nested container with React and Redux?

Due to the complexity of the application I am working on I have decided on using a nested redux container rather than passing an action as a prop down to the child components. However, this has proved to be problematic for unit testing when rendering the OuterContainer with jsdom in combination with mocha , chai and sinon .

Here is a contrived example of the view structure:

<OuterContainer>
  <div>
    <InnerContainer />
  </div>
</OuterContainer>

where OuterContainer & InnerContainer are wrapped with connect. eg:

export connect(<mapStateToProps>)(<Component>)

When running tests the error I am getting is: Invariant Violation: Could not find "store" in either the context or props of "Connect(Component)". Either wrap the root component in a `<Provider>`, or explicitly pass "store" as a prop to "Connect(Component)". Invariant Violation: Could not find "store" in either the context or props of "Connect(Component)". Either wrap the root component in a `<Provider>`, or explicitly pass "store" as a prop to "Connect(Component)".

Is there a way to unwrap or stub the InnerContainer for unit testing without having to use shallow rendering?

Wrap your component in <Provider> when testing. It's up to you whether to supply a real store or a mock with { dispatch, getState, subscribe } to it. Wrapping the outermost component in <Provider store={store}> will also make the store available to the child components at any level of nesting—just like in the app itself.

const store = createStore(reducer) // can also be a mock
ReactTestUtils.renderIntoDocument(
  <Provider store={store}>
    <OuterContainer />
  </Provider>
)

Another approach is to export both the component to be connected and the container. The container as default, of course.

export const Comp = (props) => (<p>Whatever</p>)
export default connect(...)(Comp)

Hence, you can unit test Comp .

Not sure if this is what your problem is, but I'm sure this will probably help a few people out there looking at this feed.

I had the same error and it was a simple fix:

I had forgotten to pass my component my store object in my entry file (using webpack).

I just added an attribute to the Root component "store={store}" see below:

    document.addEventListener("DOMContentLoaded", () => {
      const store = configureStore();
       ReactDOM.render(<Root store={store} />, 
     document.getElementById('content'));
    });

This was my root file code for reference as well:

    import React from 'react';
    import { Provider } from 'react-redux';
    import App from './app';

    const Root = ({ store }) => (
     <Provider store={ store }>
        <App />
     </Provider>
    );

export default Root;

Hope that helps someone!

Mock the Provider component to return the child component.

Add this before describe() .

jest.mock('Provider', () => ({children}) => children);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM