web-dev-qa-db-ja.com

カスタムreduxミドルウェアのテスト

カスタムreduxミドルウェアをユニットテストするにはどうすればよいですか?与えられたタイムアウトの後にアクションをディスパッチすることになっているこの単純な関数がありますが...私はそれにアプローチする方法がわかりません。私はこの問題に関して十分なリソースを見つけました。

const callAPiTimeoutMiddleware = store => next => (action) => {
  if (action[CALL_API]) {
    if (action[CALL_API].onTimeout) {
      setTimeout(() => {
        store.dispatch({ type: action[CALL_API].onTimeout });
      }, DEFAULT_TIMEOUT_LENGTH);
    }
  }

  return next(action);
}

これらは、受け入れられた回答に記載されているブログ投稿に基づく私のテストです:

describe('callAPiTimeoutMiddleware', () => {
  describe('With [CALL_API] symbol', () => {
    it('should dispatch custom action', () => {
      const clock = sinon.useFakeTimers();
      const fakeStore = { dispatch: sinon.spy() };
      const fakeNext = sinon.spy();
      const fakeAction = {
        [CALL_API]: {
          endpoint: 'endPoint',
          method: 'METHOD',
          types: ['REQUEST_TYPE', 'SUCCESS_TYPE', 'FAILURE_TYPE'],
          onTimeout: 'TIMEOUT_TYPE',
        },
      };

      callAPiTimeoutMiddleware(fakeStore)(fakeNext)(fakeAction);
      clock.tick(99000);

      expect(fakeStore.dispatch.calledOnce).toEqual(true);
    });


    it('should call next action', () => {
      const fakeStore = { dispatch: sinon.spy() };
      const fakeNext = sinon.spy();
      const fakeAction = {
        [CALL_API]: {
          endpoint: 'endPoint',
          method: 'METHOD',
          types: ['REQUEST_TYPE', 'SUCCESS_TYPE', 'FAILURE_TYPE'],
          onTimeout: 'TIMEOUT_TYPE',
        },
      };

      callAPiTimeoutMiddleware(fakeStore)(fakeNext)(fakeAction);

      expect(fakeNext.calledOnce).toEqual(true);
    });
  });

  describe('Without [CALL_API] symbol', () => {
    it('should NOT dispatch anything', () => {
      const clock = sinon.useFakeTimers();
      const fakeStore = { dispatch: sinon.spy() };
      const fakeNext = sinon.spy();
      const fakeAction = { type: 'SOME_TYPE' };

      callAPiTimeoutMiddleware(fakeStore)(fakeNext)(fakeAction);
      clock.tick(99000);

      expect(fakeStore.dispatch.calledOnce).toEqual(false);
    });


    it('should call next action', () => {
      const fakeStore = { dispatch: sinon.spy() };
      const fakeNext = sinon.spy();
      const fakeAction = { type: 'SOME_TYPE' };

      callAPiTimeoutMiddleware(fakeStore)(fakeNext)(fakeAction);

      expect(fakeNext.calledOnce).toEqual(true);
    });
  });
});
13
Michal

redux-thunkミドルウェアにはユニットテストが書かれています。あなたはそれを参照することができます ここ

彼はモカとチャイだけを使っています。

そして ここ 彼はあなたがあなたのreduxアプリのユニットテストを書く方法について話している。

ニース blog reduxミドルウェアとそれらのユニットテストの書き方について。

16
Thaadikkaaran

ミドルウェアのテストを実際に作成するには、さらに詳細が必要だったので、ミドルウェアテストに固有の回答を次に示します。

ミドルウェアは、多くのモックを作成することなく、非常に簡単にテストできます。チェーン矢印関数は威圧的に見えますが、それはそれらがどのように呼び出されるかだけの問題です。私はテストを手伝うためにjestを使用しましたが、すべてのjest関数を別のものに置き換えることができます。私はコードに直接入り、コメントで説明します:

import logger from './logger'; //this is your middleware
const next = jest.fn(); // middleware needs those as parameters, usually calling next(action) at the end to proceed
const store = jest.fn(); 

const action = { type: 'YOUR_ACTION_TYPE', payload: { your: 'data' }}
logger(store)(next)(action);

これは、テストでミドルウェアを呼び出す方法です。あなたの場合、ディスパッチが呼び出されたかどうかを確認したい場合は、次のようにすることができます。

// Add this in the beginning
store.dispatch = jest.fn();

// Add this after calling logger()
expect(store.dispatch.mock.calls).toEqual('whatever calls you expected');
6
Gegenwind