web-dev-qa-db-ja.com

Jestモックを使用すると、「アクションはプレーンオブジェクトである必要があります。非同期アクションにはカスタムミドルウェアを使用してください。」

1つのファイルで他のアクションをディスパッチするRedux-Thunkスタイルの関数がいくつかあります。これらのアクションの1つは、そのロジックの一部としてもう1つをディスパッチします。これは次のようになります。

export const functionToMock = () => async (dispatch) => {
    await dispatch({ type: 'a basic action' });
};

export const functionToTest = () => async (dispatch) => {
    dispatch(functionToMock());
};

私が実際に実行している場合、関数はより複雑で、それぞれ複数のアクションオブジェクトをディスパッチします。その結果、実世界functionToTestをテストするときに、実世界functionToMockをモックしたいと思います。すでにfunctionToMockを広範囲にわたってテストしていますが、functionToTestのテストでロジックを繰り返したくありません。

しかし、私がそうしようとすると、次のようになります:

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

jest.mock('../exampleActions');
const actions = require('../exampleActions');

const mockStore = configureMockStore([thunk]);

describe('example scenario showing my problem', () => {
    test('functionToTest dispatches fuctionToMock', () => {
        actions.functionToMock.mockReturnValue(() => Promise.resolve());

        const store = mockStore({});

        store.dispatch(actions.functionToTest());

        expect(actions.functionToMock.mock.calls.length).toBe(1);
    });
});

私はこのエラーを受け取ります:

 FAIL  test.js
  ● example scenario showing my problem › functionToTest dispatches fuctionToMock

    Actions must be plain objects. Use custom middleware for async actions.
        at Error (native)

      at dispatch (node_modules\redux-mock-store\dist\index-cjs.js:1:3137)
      at Object.dispatch (node_modules\redux-thunk\lib\index.js:14:16)
      at Object.<anonymous> (test.js:15:23)

(Jest、Redux、およびRedux-Thunkを含む環境でセットアップした場合、私が投稿したサンプルコードは実際にこのエラーを生成します。これは私の [〜#〜] mvce [〜#〜] です。 )

私が考えたのは、2つの関数を別のファイルに移動できるということです。残念ながら、これを行うと、プロジェクトの残りの構成がかなり劇的に壊れるので、本当に唯一のソリューションでない限り、そうするつもりはありません。

このエラーを発生させずに、functionToMockのテストでfunctionToTestをモックする方法を教えてください。

11
Kevin

1つの解決策は、functionToMockをモックすることです。この質問とその回答は、その方法を説明しています: モジュールがモックされていないときにJestにインポートされた名前付き関数をモックする方法

この答えは特に 、Babelのようなトランスパイラを使用しているときにこのアプローチを機能させるために、_exports.functionToMock_ functionToMock内のfunctionToTestの代わりに(テスト外)、次のように:

_export const functionToTest = () => async (dispatch) => {
    dispatch(exports.functionToMock());
};
_