Ad

Mock Dispatch Function Is Not Called

- 1 answer

I am writing a test for async action creator but encountered a problem where it states "Expected mock function to have been called" with:

 [{"type": "GET_LOGIN_SUCCESS", "value": true}]

But it was not called.

I am not sure where exactly the problem is. If anyone could help that will be greatly appreciated. console screenshot

Here's my actions.js

import { GET_LOGIN_SUCCESS } from './constants'

export const getLoginInfo = () => {
  return (dispatch, getState, axiosInstance) => {
    return axiosInstance.get('/api/isLogin.json')
          .then((res) => {
            dispatch({
              type: GET_LOGIN_SUCCESS,
              value: res.data.data.login
            })
            console.log('finishing dispatch')
          })
    }
}

actions.test.js

import { getLoginInfo } from './actions'
import { GET_LOGIN_SUCCESS } from './constants'


describe('async actions', () => {

    it('dispatches GET_LOGIN_SUCCESS when getting login finishes', () => {
        const axiosInstance = {
           get: jest.fn(() => Promise.resolve({ data: { data: {login : true }}}))
        }
        const dispatch = jest.fn()
        getLoginInfo()(dispatch, null, axiosInstance)
        expect(dispatch).toHaveBeenCalledWith({
            type: GET_LOGIN_SUCCESS,
            value: true
        })
    })
  })
Ad

Answer

The problem is that jest can't know that there are async task involved. So in your case you create a mock that returns a promise, and dispatch is called when the promise is resolved. As JavaScript is single threaded, it first evaluate the code in the test and all async tasks are done afterwards. So you need to make jest aware of the promise by using async/await:

describe('async actions', () => {

    it('dispatches GET_LOGIN_SUCCESS when getting login finishes', async() => {
        const p = Promise.resolve({ data: { data: {login : true }}}))
        const axiosInstance = {
           get: jest.fn(() => p
        }
        const dispatch = jest.fn()
        getLoginInfo()(dispatch, null, axiosInstance)
        await p // even it sounds not very logically you need to wait here
        expect(dispatch).toHaveBeenCalledWith({
            type: GET_LOGIN_SUCCESS,
            value: true
        })
    })

As @brian-lives-outdoors points out, getLoginInfo returns the promise as well so you could also just wait for the result of the call:

it('dispatches GET_LOGIN_SUCCESS when getting login finishes', async() => {
        const axiosInstance = {
           get: jest.fn(() => Promise.resolve({ data: { data: {login : true }}}))
        }
        const dispatch = jest.fn()
        await getLoginInfo()(dispatch, null, axiosInstance)
        expect(dispatch).toHaveBeenCalledWith({
            type: GET_LOGIN_SUCCESS,
            value: true
        })
    })

There is a epic article that describes the whole topic

Ad
source: stackoverflow.com
Ad