web-dev-qa-db-ja.com

ReactコンポーネントをテストするときにReduxストアをモックしますか?

ReactとReduxを使用しています。ChildComponentをロードするコンポーネントがあり、Reduxの状態に応じてMainComponentもロードします

    const ChooseIndex = ({ appInitMount }) => {
      return (
        <>
          <ChildComponent />
          {!appInitMount && <MainComponent />}
        </>
      );
    };


    const mapStateToProps = ({ main }) => {
      return {
        appInitMount: main.appInitMount
      };
    };

    export default connect(
      mapStateToProps,
      mapDispatchToProps
    )(ChooseIndex);

ChildComponentがロードされていることを確認するためのテストを作成しようとしています。

    import React from "react";
    import { render } from "react-testing-library";
    import ChooseIndex from "../choose-index";

    test("ChooseIndex should call ChildComponent", () => {
      const wrapper = render(
        <ChooseIndex />
      );
    });

このエラーが発生します:

エラー:キャッチされていません[不変の違反:「Connect(ChooseIndex)」のコンテキストまたは小道具のいずれにも「ストア」が見つかりませんでした。ルートコンポーネントをでラップするか、「store」を小道具として「Connect(ChooseIndex)」に明示的に渡します。]

オブジェクトリテラルをChooseIndexに渡してReduxをモックする必要がありますか?または、すべてのテストに対して(実際のアプリケーションと同様に)Reduxストアを作成する必要がありますか?

5
Evanss

コンポーネントを次のようにレンダリングしてみてください。

render(
  <Provider store={store}>
    <ChooseIndex />
  </Provider>
)

そして、アプリで使用する実際のストアを渡します。このようにして、本番環境で使用する実際のロジックをテストします。また、どのアクションがディスパッチされ、何が状態にあるかは気にしません。何がレンダリングされ、UIと対話するかを確認します。これは、最終的に重要なことです。

コンポーネントをReduxから分離し、2つを分離してテストすることは、react-testing-libraryの全体的なポイントに反します。実際のユーザーと同じようにアプリをテストしたいとします。

0
Gpx

Reduxドキュメントの writing tests セクションをチェックすると、接続されたコンポーネントをテストする例があります。

[Redux接続コンポーネント]をインポートすると、Appコンポーネント自体ではなく、connect()によって返されるラッパーコンポーネントが実際に保持されます。 Reduxとの相互作用をテストしたい場合、これは朗報です。この単体テスト用に特別に作成されたストアでラップすることができます。ただし、Reduxストアを使用せずに、コンポーネントのレンダリングのみをテストしたい場合があります。

デコレータを処理せずにアプリコンポーネント自体をテストできるようにするには、装飾されていないコンポーネントもエクスポートすることをお勧めします

ほとんどの単体テストと同様に、実際にはコンポーネントをテストする必要があり、reduxが正しく機能しているわけではありません。したがって、解決策は、コンポーネント自体をテストし、reduxがコンポーネントに渡す小道具を提供しながら、コンポーネントと接続されたコンポーネントの両方をエクスポートすることです。

import { connect } from 'react-redux'

// Use named export for unconnected component (for tests)
export class App extends Component {
  /* ... */
}

// Use default export for the connected component (for app)
export default connect(mapStateToProps)(App)
0
Wolfie