2016-03-24 11 views
26

codice completo qui: https://gist.github.com/js08/0ec3d70dfda76d7e9fb4Invariant Violazione: Impossibile trovare "store" sia nel contesto o oggetti di scena di "Connect (SportsDatabase)"

Ciao,

  • Ho una domanda in cui mostra diversi modelli per desktop e mobile in base all'ambiente di costruzione.
  • Sono riuscito a svilupparlo correttamente dove ho bisogno di nascondere il menu di navigazione per il mio modello mobile.
  • in questo momento sono in grado di scrivere un caso di test in cui recupera tutti i valori tramite proptypes e rendering correttamente
  • ma non si sa come scrivere i casi di test di unità quando il suo dispositivo mobile non deve rendere il componente di navigazione.
  • Ho provato ma sto affrontando un errore ... puoi dirmi come aggiustarlo.
  • proving codice di seguito.

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; 
    }); 

}); 

frammento di codice in cui banco di prova devono essere scritte

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

errore

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\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.<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\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) 

risposta

59

E 'piuttosto semplice. Stai provando a testare il componente wrapper generato chiamando lo connect()(MyPlainComponent). Quel componente del wrapper si aspetta di avere accesso a un negozio Redux. Normalmente quel negozio è disponibile come context.store, perché nella parte superiore della gerarchia dei componenti si avrebbe un <Provider store={myStore} />. Tuttavia, stai rendendo il tuo componente connesso da solo, senza negozio, quindi genera un errore.

Hai alcune opzioni:

  • creare un archivio e rendere un <Provider> attorno al componente collegato
  • Creare un negozio e direttamente passare in come <MyConnectedComponent store={store} />, come il componente collegato accetta anche "Negozio" come supporto
  • Non disturbare il test del componente collegato. Esporta la versione "semplice", non connessa, e prova quello. Se si esegue il test del componente normale e della funzione mapStateToProps, è possibile presumere che la versione connessa funzioni correttamente.

Probabilmente si desidera leggere la pagina "Test" nei documenti di Redux: https://redux.js.org/recipes/writing-tests.

modificare:

Dopo realtà visto che hai postato fonte, e ri-leggere il messaggio di errore, il vero problema non è con il componente SportsTopPane. Il problema è che stai cercando di rendere "completamente" SportsTopPane, che rende anche tutti i suoi figli, piuttosto che eseguire un rendering "superficiale" come nel primo caso. La riga searchComponent = <SportsDatabase sportsWholeFramework="desktop" />; sta eseguendo il rendering di un componente che presumo sia anch'esso connesso e pertanto si aspetta che un negozio sia disponibile nella funzione "contesto" di React.

A questo punto, si hanno due nuove opzioni:

  • Solo fare il rendering "superficiale" di SportsTopPane, in modo che non sei costringendolo a rendere pienamente i suoi figli
  • Se si vuole eseguire il rendering "profondo" di SportsTopPane, è necessario fornire un negozio Redux nel contesto. Consiglio vivamente di dare un'occhiata alla libreria di test Enzyme, che ti permette di fare esattamente questo. Vedere http://airbnb.io/enzyme/docs/api/ReactWrapper/setContext.html per un esempio.

Nel complesso, vorrei notare che potrebbe essere cercando di fare troppo in questo componente. Potresti prendere in considerazione la possibilità di suddividerla in pezzi più piccoli con meno logica per componente.

+0

grazie per la tua risposta .... è confuso ... è possibile aggiornare il mio test case –

+0

ho provato ma non so come fare ... puoi aggiornare nei miei casi di test –

+1

sto assumendo che in SportsTopPortion.js, si ha 'let SportsTopPortion = connect (mapStateToProps) (SomeOtherComponent)'. La risposta più semplice è quella di testare il componente _other_, non il componente restituito da 'connect'. – markerikson