Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
975 views
in Technique[技术] by (71.8m points)

reactjs - Invariant Violation: Could not find "store" in either the context or props of "Connect(SportsDatabase)"

Full code here: https://gist.github.com/js08/0ec3d70dfda76d7e9fb4

Hi,

  • I have an application where it shows different templates for desktop and mobile on basis of build environment.
  • I am successfully able to develop it where I need to hide the navigation menu for my mobile template.
  • right now I am able to write one test case where it fetches all the values through the proptypes and renders correctly
  • but not sure how to write the unit test cases when its mobile it should not render nav component.
  • I tried but I am facing an error...can you tell me how to fix it.
  • provding code below.

Test case

import {expect} from 'chai';
import React from 'react';
import TestUtils from 'react-addons-test-utils';
import {SportsTopPortion} from '../../../src/components/sports-top-portion/sports-top-portion.jsx';
require('../../test-utils/dom');


describe('"sports-top-portion" Unit Tests', function() {
    let shallowRenderer = TestUtils.createRenderer();

    let sportsContentContainerLayout ='mobile';
    let sportsContentContainerProfile = {'exists': 'hasSidebar'};
    let sportsContentContainerAuthExchange = {hasValidAccessToken: true};
    let sportsContentContainerHasValidAccessToken ='test'; 

    it('should render correctly', () => {
        shallowRenderer.render(<SportsTopPortion sportsWholeFramework={sportsContentContainerLayout} sportsPlayers={sportsContentContainerProfile} sportsAuthentication={sportsContentContainerAuthExchange} sportsUpperBar={{activeSportsLink:'test'}} />);
        //shallowRenderer.render(<SportsTopPortion sportsWholeFramework={sportsContentContainerLayout} sportsPlayers={sportsContentContainerProfile} hasValidAccessToken={sportsContentContainerHasValidAccessToken}  />);

        let renderedElement = shallowRenderer.getRenderOutput();
        console.log("renderedElement------->" + JSON.stringify(renderedElement));

        expect(renderedElement).to.exist;
    });

    it('should not render sportsNavigationComponent when sports.build is mobile', () => {
        let sportsNavigationComponent = TestUtils.renderIntoDocument(<SportsTopPortion sportsWholeFramework={sportsContentContainerLayout} sportsPlayers={sportsContentContainerProfile} sportsAuthentication={sportsContentContainerAuthExchange} sportsUpperBar={{activeSportsLink:'test'}} />);
        console.log("sportsNavigationComponent------->" + JSON.stringify(sportsNavigationComponent));

        //let footnoteContainer = TestUtils.findRenderedDOMComponentWithClass(sportsNavigationComponent, 'linkPack--standard');

        //expect(footnoteContainer).to.exist;
    });

});

Code snippet where test case need to be written

if (sports.build === 'mobile') {
    sportsNavigationComponent = <div />;
    sportsSideMEnu = <div />;
    searchComponent = <div />;
    sportsPlayersWidget = <div />;
}

Error

1) "sports-top-portion" Unit Tests should not render sportsNavigationComponent when sports.build is mobile:
     Invariant Violation: Could not find "store" in either the context or props of "Connect(SportsDatabase)". Either wrap the root component in a <Provider>, or explicitly pass "store" as a prop to "Connect(SportsDatabase)".
      at Object.invariant [as default] (C:sports-whole-page
ode_modulesinvariantinvariant.js:42:15)
      at new Connect (C:sports-whole-page
ode_modules
eact-reduxlibcomponentscreateConnect.js:135:33)
      at [object Object].ReactCompositeComponentMixin.mountComponent (C:sports-whole-page
ode_modules
eactlibReactCompositeComponent.js:148:18)
      at [object Object].wrapper [as mountComponent] (C:sports-whole-page
ode_modules
eactlibReactPerf.js:66:21)
      at Object.ReactReconciler.mountComponent (C:sports-whole-page
ode_modules
eactlibReactReconciler.js:37:35)
      at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:sports-whole-page
ode_modules
eactlibReactMultiChild.js:241:44)
      at ReactDOMComponent.Mixin._createContentMarkup (C:sports-whole-page
ode_modules
eactlibReactDOMComponent.js:591:32)
      at ReactDOMComponent.Mixin.mountComponent (C:sports-whole-page
ode_modules
eactlibReactDOMComponent.js:479:29)
      at Object.ReactReconciler.mountComponent (C:sports-whole-page
ode_modules
eactlibReactReconciler.js:37:35)
      at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:sports-whole-page
ode_modules
eactlibReactMultiChild.js:241:44)
      at ReactDOMComponent.Mixin._createContentMarkup (C:sports-whole-page
ode_modules
eactlibReactDOMComponent.js:591:32)
      at ReactDOMComponent.Mixin.mountComponent (C:sports-whole-page
ode_modules
eactlibReactDOMComponent.js:479:29)
      at Object.ReactReconciler.mountComponent (C:sports-whole-page
ode_modules
eactlibReactReconciler.js:37:35)
      at [object Object].ReactCompositeComponentMixin.mountComponent (C:sports-whole-page
ode_modules
eactlibReactCompositeComponent.js:225:34)
      at [object Object].wrapper [as mountComponent] (C:sports-whole-page
ode_modules
eactlibReactPerf.js:66:21)
      at Object.ReactReconciler.mountComponent (C:sports-whole-page
ode_modules
eactlibReactReconciler.js:37:35)
      at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:sports-whole-page
ode_modules
eactlibReactMultiChild.js:241:44)
      at ReactDOMComponent.Mixin._createContentMarkup (C:sports-whole-page
ode_modules
eactlibReactDOMComponent.js:591:32)
      at ReactDOMComponent.Mixin.mountComponent (C:sports-whole-page
ode_modules
eactlibReactDOMComponent.js:479:29)
      at Object.ReactReconciler.mountComponent (C:sports-whole-page
ode_modules
eactlibReactReconciler.js:37:35)
      at [object Object].ReactCompositeComponentMixin.mountComponent (C:sports-whole-page
ode_modules
eactlibReactCompositeComponent.js:225:34)
      at [object Object].wrapper [as mountComponent] (C:sports-whole-page
ode_modules
eactlibReactPerf.js:66:21)
      at Object.ReactReconciler.mountComponent (C:sports-whole-page
ode_modules
eactlibReactReconciler.js:37:35)
      at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:sports-whole-page
ode_modules
eactlibReactMultiChild.js:241:44)
      at ReactDOMComponent.Mixin._createContentMarkup (C:sports-whole-page
ode_modules
eactlibReactDOMComponent.js:591:32)
      at ReactDOMComponent.Mixin.mountComponent (C:sports-whole-page
ode_modules
eactlibReactDOMComponent.js:479:29)
      at Object.ReactReconciler.mountComponent (C:sports-whole-page
ode_modules
eactlibReactReconciler.js:37:35)
      at [object Object].ReactCompositeComponentMixin.mountComponent (C:sports-whole-page
ode_modules
eactlibReactCompositeComponent.js:225:34)
      at [object Object].wrapper [as mountComponent] (C:sports-whole-page
ode_modules
eactlibReactPerf.js:66:21)
      at Object.ReactReconciler.mountComponent (C:sports-whole-page
ode_modules
eactlibReactReconciler.js:37:35)
      at [object Object].ReactCompositeComponentMixin.mountComponent (C:sports-whole-page
ode_modules
eactlibReactCompositeComponent.js:225:34)
      at [object Object].wrapper [as mountComponent] (C:sports-whole-page
ode_modules
eactlibReactPerf.js:66:21)
      at Object.ReactReconciler.mountComponent (C:sports-whole-page
ode_modules
eactlibReactReconciler.js:37:35)
      at mountComponentIntoNode (C:sports-whole-page
ode_modules
eactlibReactMount.js:266:32)
      at ReactReconcileTransaction.Mixin.perform (C:sports-whole-page
ode_modules
eactlibTransaction.js:136:20)
      at batchedMountComponentIntoNode (C:sports-whole-page
ode_modules
eactlibReactMount.js:282:15)
      at ReactDefaultBatchingStrategyTransaction.Mixin.perform (C:sports-whole-page
ode_modules
eactlibTransaction.js:136:20)
      at Object.ReactDefaultBatchingStrategy.batchedUpdates (C:sports-whole-page
ode_modules
eactlibReactDefaultBatchingStrategy.js:62:19)
      at Object.batchedUpdates (C:sports-whole-page
ode_modules
eactlibReactUpdates.js:94:20)
      at Object.ReactMount._renderNewRootComponent (C:sports-whole-page
ode_modules
eactlibReactMount.js:476:18)
      at Object.wrapper [as _renderNewRootComponent] (C:sports-whole-page
ode_modules
eactlibReactPerf.js:66:21)
      at Object.ReactMount._renderSubtreeIntoContainer (C:sports-whole-page
ode_modules
eactlibReactMount.js:550:32)
      at Object.ReactMount.render (C:sports-whole-page
ode_modules
eactlibReactMount.js:570:23)
      at Object.wrapper [as render] (C:sports-whole-page
ode_modules
eactlibReactPerf.js:66:21)
      at Object.ReactTestUtils.renderIntoDocument (C:sports-whole-page
ode_modules
eactlibReactTestUtils.js:76:21)
      at Context.<anonymous> (C:/codebase/sports-whole-page/test/components/sports-top-portion/sports-top-portion-unit-tests.js:28:41)
      at callFn (C:sports-whole-page
ode_modulesmochalib
unnable.js:286:21)
      at Test.Runnable.run (C:sports-whole-page
ode_modulesmochalib
unnable.js:279:7)
      at Runner.runTest (C:sports-whole-page
ode_modulesmochalib
unner.js:421:10)
      at C:sports-whole-page
ode_modulesmochalib
unner.js:528:12
      at next (C:sports-whole-page
ode_modulesmochalib
unner.js:341:14)
      at C:sports-whole-page
ode_modulesmochalib
unner.js:351:7
      at next (C:sports-whole-page
ode_modulesmochalib
unner.js:283:14)
      at Immediate._onImmediate (C:sports-whole-page
ode_modulesmochalib
unner.js:319:5)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It's pretty simple. You're trying to test the wrapper component generated by calling connect()(MyPlainComponent). That wrapper component expects to have access to a Redux store. Normally that store is available as context.store, because at the top of your component hierarchy you'd have a <Provider store={myStore} />. However, you're rendering your connected component by itself, with no store, so it's throwing an error.

You've got a few options:

  • Create a store and render a <Provider> around your connected component
  • Create a store and directly pass it in as <MyConnectedComponent store={store} /> , as the connected component will also accept "store" as a prop
  • Don't bother testing the connected component. Export the "plain", unconnected version, and test that instead. If you test your plain component and your mapStateToProps function, you can safely assume the connected version will work correctly.

You probably want to read through the "Testing" page in the Redux docs: https://redux.js.org/recipes/writing-tests.

edit:

After actually seeing that you posted source, and re-reading the error message, the real problem is not with the SportsTopPane component. The problem is that you're trying to "fully" render SportsTopPane, which also renders all of its children, rather than doing a "shallow" render like you were in the first case. The line searchComponent = <SportsDatabase sportsWholeFramework="desktop" />; is rendering a component that I assume is also connected, and therefore expects a store to be available in React's "context" feature.

At this point, you have two new options:

  • Only do "shallow" rendering of SportsTopPane, so that you're not forcing it to fully render its children
  • If you do want to do "deep" rendering of SportsTopPane, you'll need to provide a Redux store in context. I highly suggest you take a look at the Enzyme testing library, which lets you do exactly that. See http://airbnb.io/enzyme/docs/api/ReactWrapper/setContext.html for an example.

Overall, I would note that you might be trying to do too much in this one component and might want to consider breaking it into smaller pieces with less logic per component.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...