Search code examples
unit-testingreactjsasynchronousreduxredux-thunk

Testing custom redux middleware


How do I unit test custom redux middleware? I have this simple function that is supposed to dispatch action after a given timeout but ... I have no idea how to approach it. I dint find enough resources regarding this issue.

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);
}

These are my tests based on blog post that is mentioned in the accepted answer:

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);
    });
  });
});

Solution

  • The redux-thunk middleware has unit tests written. You can refer that here

    He is using only mocha and chai.

    And here he is talking about how you can write unit tests for your redux app.

    Nice blog on redux middlewares and how to write unit tests for them.