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