15

I have several Redux-Thunk-style functions that dispatch other actions in one file. One of these actions dispatches the other as part of its logic. It looks similar to this:

export const functionToMock = () => async (dispatch) => {
    await dispatch({ type: 'a basic action' });
};

export const functionToTest = () => async (dispatch) => {
    dispatch(functionToMock());
};

In the case I'm actually running into, the functions are both much more involved and dispatch multiple action objects each. As a result, when I test my real-world functionToTest, I want to mock my real-world functionToMock. We already test functionToMock extensively, and I don't want to repeat the logic in those tests in functionToTest.

However, when I try that, like so:

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

jest.mock('../exampleActions');
const actions = require('../exampleActions');

const mockStore = configureMockStore([thunk]);

describe('example scenario showing my problem', () => {
    test('functionToTest dispatches fuctionToMock', () => {
        actions.functionToMock.mockReturnValue(() => Promise.resolve());

        const store = mockStore({});

        store.dispatch(actions.functionToTest());

        expect(actions.functionToMock.mock.calls.length).toBe(1);
    });
});

I get this error:

 FAIL  test.js
  ● example scenario showing my problem › functionToTest dispatches fuctionToMock

    Actions must be plain objects. Use custom middleware for async actions.
        at Error (native)

      at dispatch (node_modules\redux-mock-store\dist\index-cjs.js:1:3137)
      at Object.dispatch (node_modules\redux-thunk\lib\index.js:14:16)
      at Object.<anonymous> (test.js:15:23)

(The example code I posted actually produces this error if you set them up in an environment with Jest, Redux, and Redux-Thunk. It is my MVCE.)

One thought I had is that I can move the two functions into different files. Unfortunately, doing so would break pretty dramatically with how the rest of our project is organized, so I'm not willing to do that unless it is truly the only solution.

How can I mock functionToMock in my tests for functionToTest without getting this error?

Kevin
  • 14,655
  • 24
  • 74
  • 124
  • Used your example to fix a separate bug that I was having. Solution was to toss `thunk` into `const mockStore = configureMockStore([thunk]);`. Thanks! – Jake Cronin Mar 14 '21 at 20:07
  • 1
    Thank you for the response, @JakeCronin! Can you please post it as an answer? Comments are often deleted without warning - just the way the system works - so if you post an answer, more people will see it. And you'll get reputation points for your answer as well! – Kevin Mar 14 '21 at 20:47

2 Answers2

3

One solution is just to mock functionToMock. This question and its answers explain how to do so: How to mock imported named function in Jest when module is unmocked

This answer in particular explains that in order to get this approach to work when you're using a transpiler like Babel, you might need to refer to exports.functionToMock instead of functionToMock within functionToTest (outside of your tests), like so:

export const functionToTest = () => async (dispatch) => {
    dispatch(exports.functionToMock());
};
Kevin
  • 14,655
  • 24
  • 74
  • 124
2

Your example in the question helped me fix a separate bug. The solution was to toss thunk into const mockStore = configureMockStore([thunk]);. Thanks!

Jake Cronin
  • 1,002
  • 13
  • 15