web-dev-qa-db-fra.com

Se moquer de axios.create ()

J'utilise jest et axios-mock-adapter Pour tester axios les appels d'API dans redux créateurs d'actions asynchrones.

Je ne peux pas les faire fonctionner lorsque j'utilise une instance axios qui a été créée avec axios.create() comme telle:

import axios from 'axios';

const { REACT_APP_BASE_URL } = process.env;

export const ajax = axios.create({
  baseURL: REACT_APP_BASE_URL,
});

que je consommerais dans mon async action creator comme:

import { ajax } from '../../api/Ajax'

export function reportGet(data) {
  return async (dispatch, getState) => {
    dispatch({ type: REQUEST_TRANSACTION_DATA })

    try {
      const result = await ajax.post(
         END_POINT_MERCHANT_TRANSACTIONS_GET,
         data,
      )
      dispatch({ type: RECEIVE_TRANSACTION_DATA, data: result.data })
      return result.data
    } catch (e) {
      throw new Error(e);
    }
  }
}

Voici mon fichier de test:

import {
  reportGet,
  REQUEST_TRANSACTION_DATA,
  RECEIVE_TRANSACTION_DATA,
} from '../redux/TransactionRedux'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'
import { END_POINT_MERCHANT_TRANSACTIONS_GET } from 'src/utils/apiHandler'
import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'

const middlewares = [thunk]
const mockStore = configureMockStore(middlewares)
const store = mockStore({ transactions: {} })

test('get report data', async () => {
  let mock = new MockAdapter(axios)

  const mockData = {
    totalSalesAmount: 0
  }

  mock.onPost(END_POINT_MERCHANT_TRANSACTIONS_GET).reply(200, mockData)

  const expectedActions = [
    { type: REQUEST_TRANSACTION_DATA },
    { type: RECEIVE_TRANSACTION_DATA, data: mockData },
  ]

  await store.dispatch(reportGet())
  expect(store.getActions()).toEqual(expectedActions)
})

Et je n'ai qu'une seule action Received: [{"type": "REQUEST_TRANSACTION_DATA"}] Car il y a eu une erreur avec le ajax.post.

J'ai essayé de nombreuses façons de se moquer du axios.create En vain sans vraiment savoir ce que je fais .. Toute aide est appréciée.

10
kyw

OK j'ai compris. Voici comment je l'ai corrigé! J'ai fini par faire sans toutes les bibliothèques moqueuses pour axios!

Créez une maquette pour axios dans src/__mocks__:

// src/__mocks__/axios.ts

const mockAxios = jest.genMockFromModule('axios')

// this is the key to fix the axios.create() undefined error!
mockAxios.create = jest.fn(() => mockAxios)

export default mockAxios

Ensuite, dans votre fichier de test, le Gist ressemblerait à:

import mockAxios from 'axios'
import configureMockStore from 'redux-mock-store'
import thunk from 'redux-thunk'

// for some reason i need this to fix reducer keys undefined errors..
jest.mock('../../store/rootStore.ts')

// you need the 'async'!
test('Retrieve transaction data based on a date range', async () => {
  const middlewares = [thunk]
  const mockStore = configureMockStore(middlewares)
  const store = mockStore()

  const mockData = {
    'data': 123
  }

  /** 
   *  SETUP
   *  This is where you override the 'post' method of your mocked axios and return
   *  mocked data in an appropriate data structure-- {data: YOUR_DATA} -- which
   *  mirrors the actual API call, in this case, the 'reportGet'
   */
  mockAxios.post.mockImplementationOnce(() =>
    Promise.resolve({ data: mockData }),
  )

  const expectedActions = [
    { type: REQUEST_TRANSACTION_DATA },
    { type: RECEIVE_TRANSACTION_DATA, data: mockData },
  ]

  // work
  await store.dispatch(reportGet())

  // assertions / expects
  expect(store.getActions()).toEqual(expectedActions)
  expect(mockAxios.post).toHaveBeenCalledTimes(1)
})
24
kyw

Dans votre mockAdapter, vous vous moquez de la mauvaise instance. Vous auriez dû vous moquer d'ajax à la place. comme ceci, const mock = MockAdapter(ajax) C'est parce que vous ne vous moquez plus de l'instance axios mais plutôt de ajax parce que c'est celle que vous utilisez pour envoyer la demande, c'est-à-dire, vous avez créé une instance d'Axios appelée ajax lorsque vous avez fait export const ajax = axios.create...so puisque vous faites const result = await ajax.post dans votre code, c'est cette ajax instance d'axios qui devrait être moquée, pas axios dans ce cas.

0
Richard