2016-06-13 6 views
21

私は別の「接続されたコンポーネント」(つまりcontainer)をマウントするコンポーネントSampleComponentを持っています。私は(私はcomponentDidMountを必要とするので)INGのmountSampleComponentをテストしようとすると、私はエラーを取得する:React&Reduxの内部での酵素によるネストされたコンポーネントのテスト

Invariant Violation: Could not find "store" in either the context or props of "Connect(ContainerComponent)". Either wrap the root component in a , or explicitly pass "store" as a prop to "Connect(ContainerComponent)".

これをテストする最良の方法は何ですか?私は基本的にやった

答えて

4

は私redux店(とProvider)に持参し、次のようにユーティリティコンポーネントに包み:

export const CustomProvider = ({ children }) => { 
    return (
    <Provider store={store}> 
     {children} 
    </Provider> 
); 
}; 

、その後、私はSampleComponentmountし、それに対してテストを実行します。

it('contains <ChildComponent/> Component',() => { 
    const wrapper = mount(
    <CustomProvider> 
     <SampleComponent {...defaultProps} /> 
    </CustomProvider> 
); 
    expect(wrapper.find(ChildComponent)).to.have.length(1); 
}); 
+0

mountを使っているのを見て、 '' mount''を '' shallo''に置き換えるとエラーが出ます。あなたもそれに遭遇しましたか? – Mehrdad

+2

この回答は一部のケースでは機能しますが、コンポーネントのライフサイクルをテストする必要がある場合は機能しません。たとえば、 'wrapper.setProps()'を呼び出すと、 'SampleComponent'に' componentWillReceiveProps() 'がトリガーされません。 –

25

エンザイムズ・マウントは、オプションのパラメータをとります。あなたは

options.context: (Object [optional]): Context to be passed into the component

options.childContextTypes: (Object [optional]): Merged contextTypes for all children of the wrapper あるあなたがオプションでSampleComponentをマウントするだろう必要なもののために必要である二人はそうのようなオブジェクト:

const store = { 
    subscribe:() => {}, 
    dispatch:() => {}, 
    getState:() => ({ ... whatever state you need to pass in ... }) 
} 
const options = { 
    context: { store }, 
    childContextTypes: { store: React.PropTypes.object.isRequired } 
} 

const _wrapper = mount(<SampleComponent {...defaultProps} />, options) 

今すぐあなたのSampleComponentは、あなたがダウンしてコンテキストを渡します。

+2

これは完璧です!受け入れられた答えはほとんどの場合有効ですが、欠点はマウントAPIを最大限に使用する能力を失うことです。例えば、 'Provider'でコンポーネントをラップするという答えを受け入れた場合、' wrapper.state() 'APIを使用することはできません。このソリューションは、ラッパーの全範囲のメソッドを提供します。 – neurosnap

+0

これは、上記の理由で(つまり、実際にテストしようとしているコンポーネントではなく)実際の店舗の代わりに模擬店を使うことができるため、受け入れられた答えよりも良い答えです。すべての方程式から還元される。 – GTF

+2

このオプションの引数はdocsにありません、どう見ましたか?コード内で? –

1

あなたは、この問題を解決するには、名前のエクスポートを使用することができます。

あなたが持っている必要があります。

export class SampleComponent extends React.Component{ 

をしていないと、このコンポーネントをインポートします。

class SampleComponent extends React.Component{ 
... 
    render(){ 
     <div></div> 
    } 
} 

export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent) 

をあなたはクラスの前にエクスポートを追加することができますレキシブストア:

import { SampleComponent } from 'your-path/SampleComponent'; 

このソリューションでは、テストファイルにストアをインポートする必要はありません。

1

オプション1)コンテナコンポーネントをReact-ReduxのProviderコンポーネントでラップすることができます。したがって、このアプローチでは、実際にストアを参照してプロバイダに渡し、テスト対象のコンポーネントを内部に作成します。この方法の利点は、実際にテストのカスタムストアを作成できることです。この方法は、コンポーネントのRedux関連部分をテストする場合に便利です。 オプション2) Redux関連のテストを気にする必要はないかもしれません。コンポーネントのレンダリングとローカルの状態関連の動作をテストするだけの場合は、コンポーネントの未接続プレーンバージョンの名前付きエクスポートを追加するだけです。あなたのクラスに "export"キーワードを追加すると、クラスを2つの方法で中括弧{}でインポートできるようになりました。例:私はそこに誰にも役立ちます願ってい

import MyComponent from 'your-path/MyComponent'; // it needs a store because you use "default export" with connect 
import {MyComponent} from 'your-path/MyComponent'; // don't need store because you use "export" on top of your class. 

:あなたのテストファイル上の

export class MyComponent extends React.Component{ render(){ ... }} 

... 

export default connect(mapStateToProps, mapDispatchToProps)(MyComponent) 

後で

関連する問題