Kode lengkap di sini: https://gist.github.com/js08/0ec3d70dfda76d7e9fb4
Hai,
- Saya memiliki aplikasi di mana ia menunjukkan template yang berbeda untuk desktop dan seluler berdasarkan lingkungan build.
- Saya berhasil mengembangkannya di mana saya perlu menyembunyikan menu navigasi untuk templat seluler saya.
- saat ini saya dapat menulis satu test case di mana ia mengambil semua nilai melalui proptypes dan merender dengan benar
- tetapi tidak yakin bagaimana menulis unit test case ketika mobile-nya seharusnya tidak membuat komponen nav.
- Saya mencoba tetapi saya menghadapi kesalahan ... dapatkah Anda memberi tahu saya cara memperbaikinya?
- kode provding di bawah ini.
Kasus cobaan
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;
});
});
Cuplikan kode tempat test case perlu ditulis
if (sports.build === 'mobile') {
sportsNavigationComponent = <div />;
sportsSideMEnu = <div />;
searchComponent = <div />;
sportsPlayersWidget = <div />;
}
Kesalahan
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)
. Jawaban termudah adalah menguji komponen lain itu , bukan komponen yang dikembalikanconnect
.searchComponent = <SportsDatabase sportsWholeFramework="desktop" />;
. Itu adalah komponen yang terhubung yang mengharapkan toko dan rusak. Jadi, dua saran baru: lakukan saja rendering SportsTopPane yang dangkal, atau gunakan perpustakaan seperti Enzyme untuk menguji. Lihat airbnb.io/enzyme/docs/api/ReactWrapper/setContext.html .Kemungkinan solusi yang berhasil bagi saya dengan bercanda
sumber
Seperti yang disarankan oleh dokumen resmi redux, lebih baik untuk mengekspor komponen yang tidak terhubung juga.
Untuk dapat menguji komponen Aplikasi itu sendiri tanpa harus berurusan dengan dekorator, kami sarankan Anda untuk juga mengekspor komponen yang tidak didekorasi:
Karena ekspor default masih merupakan komponen yang dihiasi, pernyataan impor yang digambarkan di atas akan berfungsi seperti sebelumnya sehingga Anda tidak perlu mengubah kode aplikasi Anda. Namun, Anda sekarang dapat mengimpor komponen Aplikasi yang tidak didekorasi dalam file pengujian Anda seperti ini:
Dan jika Anda membutuhkan keduanya:
Di aplikasi itu sendiri, Anda masih akan mengimpornya secara normal:
Anda hanya akan menggunakan ekspor yang disebutkan untuk pengujian.
sumber
Ketika kita menyusun aplikasi react-redux, kita seharusnya melihat struktur di mana di bagian atas kita memiliki
Provider
tag yang memiliki instance dari toko redux.Itu
Provider
tag kemudian menjadikan komponen orang tua Anda, memungkinkan menyebutnyaApp
komponen yang pada gilirannya menjadikan setiap komponen lain di dalam aplikasi.Inilah bagian kuncinya, ketika kita membungkus komponen dengan
connect()
fungsi,connect()
fungsi itu mengharapkan untuk melihat beberapa komponen induk dalam hierarki yang memilikiProvider
tag.Jadi, ketika Anda meletakkan
connect()
fungsi di sana, itu akan mencari hierarki dan mencoba untuk menemukanProvider
.Itulah yang Anda inginkan terjadi, tetapi di lingkungan pengujian Anda, aliran itu mogok.
Mengapa?
Mengapa?
Ketika kita kembali ke file tes sportsDatabase yang diasumsikan, Anda harus menjadi komponen sportsDatabase dengan sendirinya dan kemudian mencoba membuat komponen itu dengan sendirinya dalam isolasi.
Jadi pada dasarnya apa yang Anda lakukan di dalam file tes hanya mengambil komponen itu dan hanya membuangnya di alam bebas dan tidak memiliki ikatan dengan apa pun
Provider
atau menyimpan di atasnya dan itulah sebabnya Anda melihat pesan ini.Tidak ada toko atau
Provider
tag dalam konteks atau penyangga komponen itu dan komponen tersebut membuat kesalahan karena ingin melihatProvider
tag atau toko dalam hierarki induknya.Jadi itulah arti kesalahan itu.
sumber
dalam kasus saya saja
shallow(<Login />, { context: { store } });
sumber
hanya melakukan impor ini {dangkal, mount} dari "enzim";
sumber
Bagi saya itu masalah impor, semoga membantu. Impor default oleh WebStorm salah.
menggantikan
dengan
sumber
Ini terjadi pada saya ketika saya memutakhirkan. Saya harus menurunkan versi kembali.
react-redux ^ 5.0.6 → ^ 7.1.3
sumber
di akhir Index.js Anda perlu menambahkan Kode ini:
sumber