не вызывается функция макетной отправки

#reactjs #jestjs #enzyme

#reactjs ( реакция ) #jestjs #фермент #reactjs

Вопрос:

Я пишу тест для async action creator, но столкнулся с проблемой, когда в нем указано, что «Ожидаемая функция макета была вызвана» с:

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

Но она не была вызвана.

Я не уверен, в чем именно заключается проблема. Если кто-нибудь может помочь, это будет высоко оценено. скриншот консоли

Вот мой 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
        })
    })
  })
  

Комментарии:

1. Может быть, попробуйте поместить catch в actions.js и console.log там, чтобы посмотреть, есть ли ошибка.

Ответ №1:

Проблема в том, что jest не может знать, что задействована асинхронная задача. Итак, в вашем случае вы создаете макет, который возвращает обещание, и отправка вызывается, когда обещание выполнено. Поскольку JavaScript является однопоточным, он сначала оценивает код в тесте, а все асинхронные задачи выполняются впоследствии. Итак, вам нужно ознакомить jest с обещанием, используя 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
        })
    })
  

Как указывает @brian-lives-outdoors, getLoginInfo также возвращает обещание, поэтому вы также можете просто дождаться результата вызова:

 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
        })
    })
  

Есть эпическая статья, которая описывает всю тему

Комментарии:

1. Функция, возвращаемая при вызове, getLoginInfo возвращает Promise , поэтому единственные необходимые изменения — создать тестовую функцию async и изменить эту одну строку на await getLoginInfo()(dispatch, null, axiosInstance);

2. @brian-lives-outdoors верно, это тоже сработало бы. Я подумал, что это будет легче понять, когда можно будет увидеть, чего вам нужно ждать. Я обновлю свой ответ, чтобы отразить и ваше решение.

3. В дополнение к приведенным выше ответам, например, при рендеринге перехватов вы можете обернуть ожидаемую часть с waitFor(() => expect(...));