Vollständiger Code hier: https://gist.github.com/js08/0ec3d70dfda76d7e9fb4
Hallo,
- Ich habe eine Anwendung, in der verschiedene Vorlagen für Desktop und Mobile basierend auf der Build-Umgebung angezeigt werden.
- Ich kann es erfolgreich dort entwickeln, wo ich das Navigationsmenü für meine mobile Vorlage ausblenden muss.
- Im Moment kann ich einen Testfall schreiben, in dem alle Werte durch die Proptypen abgerufen und korrekt gerendert werden
- aber nicht sicher, wie man die Unit-Testfälle schreibt, wenn sein Handy keine Navi-Komponente rendern soll.
- Ich habe es versucht, aber ich habe einen Fehler festgestellt. Können Sie mir sagen, wie ich ihn beheben kann?
- Testcode unten.
Testfall
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, in das der Testfall geschrieben werden muss
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\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)
let SportsTopPortion = connect(mapStateToProps)(SomeOtherComponent)
. Die einfachste Antwort besteht darin, diese andere Komponente zu testen , nicht die von zurückgegebene Komponenteconnect
.searchComponent = <SportsDatabase sportsWholeFramework="desktop" />;
. Das ist die verbundene Komponente, die ein Geschäft erwartet und bricht. Also zwei neue Vorschläge: entweder nur flaches Rendern von SportsTopPane oder Verwenden einer Bibliothek wie Enzyme zum Testen. Siehe airbnb.io/enzyme/docs/api/ReactWrapper/setContext.html .Mögliche Lösung, die bei mir mit Scherz funktioniert hat
quelle
Wie aus den offiziellen Dokumenten von Redux hervorgeht, ist es besser, auch die nicht verbundene Komponente zu exportieren.
Um die App-Komponente selbst testen zu können, ohne sich um den Dekorateur kümmern zu müssen, empfehlen wir Ihnen, auch die nicht dekorierte Komponente zu exportieren:
Da der Standardexport immer noch die dekorierte Komponente ist, funktioniert die oben abgebildete Importanweisung wie zuvor, sodass Sie Ihren Anwendungscode nicht ändern müssen. Sie können die nicht dekorierten App-Komponenten jetzt jedoch wie folgt in Ihre Testdatei importieren:
Und wenn Sie beides brauchen:
In der App selbst würden Sie sie weiterhin normal importieren:
Sie würden den genannten Export nur für Tests verwenden.
quelle
Wenn wir eine React-Redux-Anwendung zusammenstellen, sollten wir eine Struktur erwarten, in der wir oben das
Provider
Tag haben, das eine Instanz eines Redux-Speichers enthält.Dieses
Provider
Tag rendert dann Ihre übergeordnete Komponente. Nennen wir es dieApp
Komponente, die wiederum jede andere Komponente in der Anwendung rendert.Hier ist der Schlüsselteil: Wenn wir eine Komponente mit der
connect()
Funktionconnect()
umschließen, erwartet diese Funktion, dass eine übergeordnete Komponente in der Hierarchie mit demProvider
Tag angezeigt wird.Wenn Sie also die
connect()
Funktion dort einfügen, wird die Hierarchie nachgeschlagen und versucht, die zu findenProvider
.Das ist, was Sie wollen, aber in Ihrer Testumgebung bricht dieser Fluss zusammen.
Warum?
Warum?
Wenn wir zur angenommenen sportsDatabase-Testdatei zurückkehren, müssen Sie die sportsDatabase-Komponente für sich sein und dann versuchen, diese Komponente für sich isoliert zu rendern.
Was Sie also in dieser Testdatei tun, ist im Wesentlichen, diese Komponente zu nehmen und sie einfach in der Wildnis
Provider
wegzuwerfen, und sie hat keine Verbindungen zu irgendwelchen oder Speichern darüber, und deshalb sehen Sie diese Nachricht.Provider
Der Kontext oder die Requisite dieser Komponente enthält kein Speichern oder Tag. Daher gibt die Komponente einen Fehler aus, da sie einProvider
Tag oder einen Speicher in ihrer übergeordneten Hierarchie anzeigen möchte .Das ist es also, was dieser Fehler bedeutet.
quelle
in meinem Fall nur
shallow(<Login />, { context: { store } });
quelle
jus mache diesen Import {flach, montiert} von "Enzym";
quelle
Für mich war es ein Importproblem, hoffe es hilft. Der Standardimport von WebStorm war falsch.
ersetzen
mit
quelle
Dies ist mir beim Upgrade passiert. Ich musste zurückstufen.
React-Redux ^ 5.0.6 → ^ 7.1.3
quelle
Am Ende Ihres Index.js müssen Sie diesen Code hinzufügen:
quelle