別の「接続されたコンポーネント」(つまり、SampleComponent
)をマウントするコンポーネントcontainer
があります。 SampleComponent
ingでmount
をテストしようとすると(componentDidMount
が必要なため)、エラーが発生します。
不変の違反:コンテキストまたは「Connect(ContainerComponent)」の小道具のいずれにも「ストア」が見つかりませんでした。ルートコンポーネントをにラップするか、「store」をpropとして「Connect(ContainerComponent)」に明示的に渡します。
これをテストする最良の方法は何ですか?
私が本質的にやったことは、redux
ストア(およびProvider
)を持ち込み、次のようにユーティリティコンポーネントにラップすることでした。
export const CustomProvider = ({ children }) => {
return (
<Provider store={store}>
{children}
</Provider>
);
};
次に、mount
SampleComponent
をテストし、それに対してテストを実行します。
it('contains <ChildComponent/> Component', () => {
const wrapper = mount(
<CustomProvider>
<SampleComponent {...defaultProps} />
</CustomProvider>
);
expect(wrapper.find(ChildComponent)).to.have.length(1);
});
酵素のマウントはオプションのパラメーターを取ります。必要なものに必要な2つは
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は、指定したコンテキストをconnected component
に渡します。
名前のエクスポートを使用して、この問題を解決できます。
次のものが必要です。
class SampleComponent extends React.Component{
...
render(){
<div></div>
}
}
export default connect(mapStateToProps, mapDispatchToProps)(SampleComponent)
クラスの前にエクスポートを追加できます:
export class SampleComponent extends React.Component{
そして、このコンポーネントをreduxストアなしでインポートします。
import { SampleComponent } from 'your-path/SampleComponent';
このソリューションを使用すると、ストアをテストファイルにインポートする必要がありません。
テスト内でReact-ReduxのProviderコンポーネントでコンテナコンポーネントをラップできます。したがって、このアプローチでは、実際にストアを参照し、プロバイダーに渡し、内部でテスト対象のコンポーネントを作成します。このアプローチの利点は、テスト用のカスタムストアを実際に作成できることです。このアプローチは、コンポーネントのRedux関連部分をテストする場合に役立ちます。
たぶん、Redux関連の部分をテストすることを気にしないかもしれません。コンポーネントのレンダリングとローカル状態関連の動作をテストするだけの場合は、コンポーネントの接続されていないプレーンバージョンの名前付きエクスポートを追加するだけです。そして、クラスに「export」キーワードを追加するときを明確にするために、基本的には、クラスを中括弧{}を使用してまたはインポートしないで2つの方法でインポートできると言っています。例:
export class MyComponent extends React.Component{ render(){ ... }}
...
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent)
テストファイルの後で:
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.
私はそこにいるだれでも助けることを望みます。
redux-mock-store を使用するオプションもあります。
Redux非同期アクションクリエーターとミドルウェアをテストするための模擬ストア。モックストアは、テストのアクションログとして機能するディスパッチされたアクションの配列を作成します。
モックストアは、Reduxに必要なストアオブジェクトに必要なメソッドを提供します。オプションのミドルウェアとアプリ固有の初期状態を指定できます。
import configureStore from 'redux-mock-store'
const middlewares = []
const mockStore = configureStore(middlewares)
const initialState = {}
const store = mockStore(initialState)
const wrapper = mount(<SampleComponent store={store}/>)
デコレータ構文をよりテストしやすくするために、これを作成しました: https://www.npmjs.com/package/babel-plugin-undecorate
input:
@anyOldClassDecorator
export class AnyOldClass {
@anyOldMethodDecorator
method() {
console.log('hello');
}
}
output:
@anyOldClassDecorator
export class AnyOldClass {
@anyOldMethodDecorator
method() {
console.log('hello');
}
}
export class __undecorated__AnyOldClass {
method() {
console.log('hello');
}
}
うまくいけば、これが固体オプション3を提供できます!