Testing custom redux middleware

Michal picture Michal · Dec 20, 2016 · Viewed 7.6k times · Source

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

Answer

Thaadikkaaran picture Thaadikkaaran · Dec 20, 2016

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.