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);
});
});
});
Show activity on this post. import * as redux from "react-redux"; describe('dispatch mock', function(){ it('should mock dispatch', function(){ //arrange const useDispatchSpy = jest. spyOn(redux, 'useDispatch'); const mockDispatchFn = jest. fn() useDispatchSpy.
A redux middleware is nothing more than a function which is invoked on every action and we can do almost anything e.g Data manipulations, popups, confirmations, API response validation and more, before pushing the updates to the reducers followed by the state change.
Steps: extract each mapDispatchToProps property as a separate action creator function in another file. extract each mapStateToProps property as a separate selector function in another file. write tests for the selectors and action creators.
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.
I needed some more details to actually create tests for the middleware, so here is my answer specific to the middleware test:
Middlewares can be tested very easily without doing a lot of mocking. The chained arrow functions appear intimidating, but it is just a matter of how they are called. I used jest to help me testing but you can replace all jest functions with something else. I'll get right into the code and explain in comments:
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);
This is how you call your middleware in a test. In your case if you want to check if dispatch has been called you could do something like this:
// Add this in the beginning
store.dispatch = jest.fn();
// Add this after calling logger()
expect(store.dispatch.mock.calls).toEqual('whatever calls you expected');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With