Here's a generalized example:
// myActions.js
export const actionOne = () => (dispatch) => {
dispatch(actionTwo());
};
export const actionTwo = () => ({
type: 'SOME_TYPE',
});
I would like to test that actionTwo
has been either called or dispatched, ideally without the test knowing anything about what is going on in actionTwo
, because I have a different test that takes care of that.
I am using redux-mock-store
to dispatch the tested action to a mocked store and calling store.getActions()
to find out if the expected actions within the thunk action creator have been dispatched. I feel it is not the right way to go in this particular scenario because then the test would test more than it should. I really only want to know if actionTwo
has been called at all.
I'm aware of spyOn
and jest.mock
, but I've been unable to use either to solve my problem. Here's what the generalized test looks like:
// myActions.test.js
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import * as actions from 'myActions';
const mockStore = configureMockStore([thunk]);
test('actionOne', () => {
const store = mockStore();
return store.dispatch(actions.actionOne()).then(() => {
// TODO: check if actions.actionTwo was called
});
});
test('actionTwo', () => {
const store = mockStore();
return store.dispatch(actions.actionTwo()).then(() => {
expect(store.getActions()).toEqual([{ type: 'SOME_TYPE' }]);
});
});
I'm grateful for any suggestions!
Took me a while, but I figured it out. It's not ideal (because it involves a small change to the tested code), but the closest to ideal that I could get.
// myActions.js
export const actionOne = () => (dispatch) => {
dispatch(exports.actionTwo());
};
export const actionTwo = () => ({
type: 'SOME_TYPE',
});
The important change is the exports.actionTwo()
. That way, I make sure that I can overwrite the function's implementation from the outside (the test file) and the overwriting function will actually be called from within the imported file.
Now I can simply add something like the following to my test file:
beforeEach(() => {
actions.actionTwo = jest.fn(() => () => Promise.resolve());
});
actionTwo
is now being mocked and I can use toBeCalledWith
and other expectations on it. If I wish to test its actual implementation within the same test file, I can store it in a variable before calling beforeEach
, like:
const actionTwo = actions.actionTwo;
And then in the test setup for its implementation, I can overwrite the mock calling
actions.actionTwo = actionTwo;
That's it. Now I can make sure to ignore all side effects from an exported function and test it as an actual unit.