Violation d’invariant: impossible de trouver «stocker» dans le contexte ou les accessoires de «Connect (SportsDatabase)»

Code complet ici: https://gist.github.com/js08/0ec3d70dfda76d7e9fb4

Salut,

  • J’ai une application où il affiche différents modèles pour le bureau et le mobile sur la base de l’environnement de construction.
  • Je parviens à le développer là où je dois masquer le menu de navigation de mon modèle mobile.
  • en ce moment je suis capable d’écrire un cas de test où il récupère toutes les valeurs à travers les proptypes et rend correctement
  • mais pas sûr comment écrire les cas de test unitaire quand son mobile, il ne devrait pas rendre composant nav.
  • J’ai essayé mais je suis confronté à une erreur … pouvez-vous me dire comment le réparer?
  • code de preuve ci-dessous.

Cas de test

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(); //shallowRenderer.render(); let renderedElement = shallowRenderer.getRenderOutput(); console.log("renderedElement------->" + JSON.ssortingngify(renderedElement)); expect(renderedElement).to.exist; }); it('should not render sportsNavigationComponent when sports.build is mobile', () => { let sportsNavigationComponent = TestUtils.renderIntoDocument(); console.log("sportsNavigationComponent------->" + JSON.ssortingngify(sportsNavigationComponent)); //let footnoteContainer = TestUtils.findRenderedDOMComponentWithClass(sportsNavigationComponent, 'linkPack--standard'); //expect(footnoteContainer).to.exist; }); }); 

Extrait de code dans lequel un scénario de test doit être écrit

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

Erreur

 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 , or explicitly pass "store" as a prop to "Connect(SportsDatabase)". at Object.invariant [as default] (C:\sports-whole-page\node_modules\invariant\invariant.js:42:15) at new Connect (C:\sports-whole-page\node_modules\react-redux\lib\components\createConnect.js:135:33) at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:148:18) at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21) at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35) at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:\sports-whole-page\node_modules\react\lib\ReactMultiChild.js:241:44) at ReactDOMComponent.Mixin._createContentMarkup (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:591:32) at ReactDOMComponent.Mixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:479:29) at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35) at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:\sports-whole-page\node_modules\react\lib\ReactMultiChild.js:241:44) at ReactDOMComponent.Mixin._createContentMarkup (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:591:32) at ReactDOMComponent.Mixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:479:29) at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35) at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:225:34) at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21) at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35) at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:\sports-whole-page\node_modules\react\lib\ReactMultiChild.js:241:44) at ReactDOMComponent.Mixin._createContentMarkup (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:591:32) at ReactDOMComponent.Mixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:479:29) at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35) at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:225:34) at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21) at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35) at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (C:\sports-whole-page\node_modules\react\lib\ReactMultiChild.js:241:44) at ReactDOMComponent.Mixin._createContentMarkup (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:591:32) at ReactDOMComponent.Mixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactDOMComponent.js:479:29) at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35) at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:225:34) at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21) at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35) at [object Object].ReactCompositeComponentMixin.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactCompositeComponent.js:225:34) at [object Object].wrapper [as mountComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21) at Object.ReactReconciler.mountComponent (C:\sports-whole-page\node_modules\react\lib\ReactReconciler.js:37:35) at mountComponentIntoNode (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:266:32) at ReactReconcileTransaction.Mixin.perform (C:\sports-whole-page\node_modules\react\lib\Transaction.js:136:20) at batchedMountComponentIntoNode (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:282:15) at ReactDefaultBatchingStrategyTransaction.Mixin.perform (C:\sports-whole-page\node_modules\react\lib\Transaction.js:136:20) at Object.ReactDefaultBatchingStrategy.batchedUpdates (C:\sports-whole-page\node_modules\react\lib\ReactDefaultBatchingStrategy.js:62:19) at Object.batchedUpdates (C:\sports-whole-page\node_modules\react\lib\ReactUpdates.js:94:20) at Object.ReactMount._renderNewRootComponent (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:476:18) at Object.wrapper [as _renderNewRootComponent] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21) at Object.ReactMount._renderSubtreeIntoContainer (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:550:32) at Object.ReactMount.render (C:\sports-whole-page\node_modules\react\lib\ReactMount.js:570:23) at Object.wrapper [as render] (C:\sports-whole-page\node_modules\react\lib\ReactPerf.js:66:21) at Object.ReactTestUtils.renderIntoDocument (C:\sports-whole-page\node_modules\react\lib\ReactTestUtils.js:76:21) at Context. (C:/codebase/sports-whole-page/test/components/sports-top-portion/sports-top-portion-unit-tests.js:28:41) at callFn (C:\sports-whole-page\node_modules\mocha\lib\runnable.js:286:21) at Test.Runnable.run (C:\sports-whole-page\node_modules\mocha\lib\runnable.js:279:7) at Runner.runTest (C:\sports-whole-page\node_modules\mocha\lib\runner.js:421:10) at C:\sports-whole-page\node_modules\mocha\lib\runner.js:528:12 at next (C:\sports-whole-page\node_modules\mocha\lib\runner.js:341:14) at C:\sports-whole-page\node_modules\mocha\lib\runner.js:351:7 at next (C:\sports-whole-page\node_modules\mocha\lib\runner.js:283:14) at Immediate._onImmediate (C:\sports-whole-page\node_modules\mocha\lib\runner.js:319:5) 

C’est assez simple Vous essayez de tester le composant wrapper généré en appelant connect()(MyPlainComponent) . Ce composant wrapper s’attend à avoir access à un magasin Redux. Normalement, ce magasin est disponible en tant que context.store , car en haut de votre hiérarchie de composants, vous disposez d’un . Cependant, vous restituez vous-même votre composant connecté, sans magasin, ce qui génère une erreur.

Vous avez quelques options:

  • Créer un magasin et rendre un autour de votre composant connecté
  • Créez un magasin et transmettez-le directement en tant que , car le composant connecté acceptera également le “store” en tant que prop
  • Ne vous souciez pas de tester le composant connecté. Exportez la version “plain”, non connectée, et testez-la à la place. Si vous testez votre composant ordinaire et votre fonction mapStateToProps , vous pouvez supposer que la version connectée fonctionnera correctement.

Vous voulez probablement lire la page “Testing” dans les documents Redux: https://redux.js.org/recipes/writing-tests .

éditer :

Après avoir constaté que vous avez publié la source et relu le message d’erreur, le véritable problème ne concerne pas le composant SportsTopPane. Le problème est que vous essayez de rendre “entièrement” SportsTopPane, qui rend également tous ses enfants, plutôt que de faire un rendu “superficiel” comme dans le premier cas. La ligne searchComponent = ; rend un composant que je suppose également connecté, et attend donc qu’un magasin soit disponible dans la fonction “contexte” de React.

À ce stade, vous avez deux nouvelles options:

  • Ne faites qu’un rendu “superficiel” de SportsTopPane, afin de ne pas le forcer à rendre complètement ses enfants
  • Si vous souhaitez effectuer un rendu “approfondi” de SportsTopPane, vous devez fournir un magasin Redux en contexte. Je vous suggère fortement de consulter la bibliothèque de tests d’enzymes, qui vous permet de faire exactement cela. Voir http://airbnb.io/enzyme/docs/api/ReactWrapper/setContext.html pour un exemple.

Dans l’ensemble, je noterais que cela pourrait être trop difficile dans cette composante. Vous voudrez peut-être envisager de le décomposer en morceaux plus petits avec moins de logique par composant.

Comme le suggèrent les documents officiels de redux, mieux vaut également exporter le composant non connecté.

Afin de pouvoir tester le composant App lui-même sans avoir à traiter avec le décorateur, nous vous recommandons d’exporter également le composant non décoré:

 import { connect } from 'react-redux' // Use named export for unconnected component (for tests) export class App extends Component { /* ... */ } // Use default export for the connected component (for app) export default connect(mapStateToProps)(App) 

Étant donné que l’exportation par défaut est toujours le composant décoré, la déclaration d’importation illustrée ci-dessus fonctionnera comme précédemment, vous n’aurez donc pas à modifier votre code d’application. Cependant, vous pouvez maintenant importer les composants App non décorés dans votre fichier de test comme ceci:

 // Note the curly braces: grab the named export instead of default export import { App } from './App' 

Et si vous avez besoin des deux:

 import ConnectedApp, { App } from './App' 

Dans l’application elle-même, vous importez toujours normalement:

 import App from './App' 

Vous utiliseriez uniquement l’exportation nommée pour les tests.

Solution possible qui a fonctionné pour moi avec blague

 import React from "react"; import { shallow } from "enzyme"; import { Provider } from "react-redux"; import configureMockStore from "redux-mock-store"; import TestPage from "../TestPage"; const mockStore = configureMockStore(); const store = mockStore({}); describe("Testpage Component", () => { it("should render without throwing an error", () => { expect( shallow(    ).exists(

Test page

) ).toBe(true); }); });