Search code examples
reactjsreduxjestjsredux-thunk

How do you mock the resolved value of an awaited dispatch


Let's say I have a thunk:

import fetchSomeData from '/path/to/fetchSomeData'

const myAction = () => async dispatch => {
    ...
    const data = await dispatch(fetchSomeData()) // `fetchSomeData` is itself a thunk
    ...
}

And in my test file, I want to specify what the data is I want the fetchSomeData function to return:

import fetchSomeData from '/path/to/fetchSomeData'
import myAction from '/path/to/myAction'

jest.mock('/path/to/fetchSomeData')

describe('test function', () => {
    beforeEach(() => { jest.clearAllMocks() })

    it('tests the function', async () => {
        const dispatchMock = jest.fn()
        fetchSomeData.mockResolvedValueOnce({ value: 'some dummy data' })

        await myAction()(dispatchMock)

        expect(dispatchMock).toHaveBeenCalledTimes(1)
    })
})

However, when doing this, the data that I'm expecting to be my dummy data, always comes back as undefined.

What am I doing wrong?

In our package.json, we have jest 27.5.1 and babel-jest 27.1.0


Solution

  • Because the dispatch function is mocked. You should use the real implementation of store.dispatch.

    e.g.

    fetchSomeData.js:

    const fetchSomeData = () => {};
    export default fetchSomeData;
    

    index.js:

    import fetchSomeData from './fetchSomeData';
    
    const myAction = () => async (dispatch) => {
      const data = await dispatch(fetchSomeData());
      console.log('🚀 ~ myAction ~ data:', data);
    };
    
    export default myAction;
    

    index.test.js:

    import fetchSomeData from './fetchSomeData';
    import myAction from '.';
    import { createStore, applyMiddleware } from 'redux';
    import thunk from 'redux-thunk';
    
    jest.mock('./fetchSomeData');
    
    describe('test function', () => {
      beforeEach(() => {
        jest.clearAllMocks();
      });
    
      it('tests the function', async () => {
        fetchSomeData.mockReturnValue({ type: 'FETCH_SOME_DATA', value: 'some dummy data' });
    
        const mockStore = createStore(() => {}, applyMiddleware(thunk));
        const dispatchSpy = jest.spyOn(mockStore, 'dispatch');
    
        await myAction()(mockStore.dispatch);
    
        expect(dispatchSpy).toHaveBeenCalledTimes(1);
      });
    });
    

    Test result:

    > jest -o
    
      console.log
        🚀 ~ myAction ~ data: { type: 'FETCH_SOME_DATA', value: 'some dummy data' }
    
          at stackoverflow/78234718/index.js:5:11
    
     PASS  stackoverflow/78234718/index.test.js
      test function
        √ tests the function (18 ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        1.981 s, estimated 2 s
    Ran all test suites related to changed files.
    

    package versions:

    "redux-thunk": "^2.4.2",
    "redux": "^4.2.1",