模拟内部 axios.create()

IT技术 javascript reactjs axios jestjs create-react-app
2021-04-17 06:43:13

我正在使用jestaxios-mock-adapter测试异步操作创建器中的axiosAPI 调用redux

当我使用axios这样创建实例时,我无法让它们工作axios.create()

import axios from 'axios';

const { REACT_APP_BASE_URL } = process.env;

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

我会async action creator这样消费它

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

这是我的测试文件:

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

我只得到一个操作,Received: [{"type": "REQUEST_TRANSACTION_DATA"}]因为ajax.post.

我已经尝试了很多方法来模拟axios.create没有真正知道我在做什么的情况下无济于事..任何帮助表示赞赏。

5个回答

好,我知道了。这是我修复它的方法!我最终没有任何模拟库axios

axiosin创建一个模拟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

然后在您的测试文件中,要点如下所示:

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)
})
我知道这有点旧,但你需要返回 Promise.resolve ;)
2021-05-23 06:43:13
我一直在努力解决这个问题。我尝试了您的解决方案,但没有奏效。你能看看我的具体问题吗?谢谢!stackoverflow.com/questions/60745903/...
2021-05-24 06:43:13
@ReinierKaper 很确定返回是隐含在箭头函数模式中的 :)
2021-06-06 06:43:13
你是我的英雄 :)
2021-06-21 06:43:13
建议创建与node_modules同级的__mocks__目录,更多定义在这里
2021-06-21 06:43:13

如果你需要创建玩笑测试,嘲笑axioscreate特定测试(并且不需要模拟Axios公司所有的测试用例,在其他的答案中提到),你也可以使用:

const axios = require("axios");

jest.mock("axios");

beforeAll(() => {
    axios.create.mockReturnThis();
});

test('should fetch users', () => {
    const users = [{name: 'Bob'}];
    const resp = {data: users};
    axios.get.mockResolvedValue(resp);

    // or you could use the following depending on your use case:
    // axios.get.mockImplementation(() => Promise.resolve(resp))

    return Users.all().then(data => expect(data).toEqual(users));
});

这是没有create. 区别在于添加axios.create.mockReturnThis()

试试这个,我明白了 TypeError: axios.create.mockReturnThis is not a function
2021-05-26 06:43:13
只要您没有在模拟运行之前调用 axios.create 就可以完美运行。很好谢谢。@mikemaccana 我会确保你在这种情况下正确地嘲笑 axios,如第二行所示
2021-06-19 06:43:13

在您的 mockAdapter 中,您正在嘲笑错误的实例。你应该嘲笑ajax。像这样,const mock = MockAdapter(ajax) 这是因为您现在不是在模拟实例,axios而是ajax因为它是您用来发送请求的实例,即,您在export const ajax = axios.create...这样做时创建了一个名为 ajax 的 axios 实例,因为您正在const result = await ajax.post代码中执行此操作,它ajax应该被嘲笑的 axios 实例,而不是axios那种情况。

我有另一个解决方案。

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 { ajax } from '../../api/Ajax' // axios instance
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)
  let mock = new MockAdapter(ajax) // this here need to mock axios instance

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

以下代码有效!

   jest.mock("axios", () => {
        return {
            create: jest.fn(() => axios),
            post: jest.fn(() => Promise.resolve()),
        };
    });
唯一需要导入的东西 import axios from 'axios'
2021-06-20 06:43:13