Javascript 模拟内部axios.create()

Javascript 模拟内部axios.create(),javascript,reactjs,axios,jestjs,create-react-app,Javascript,Reactjs,Axios,Jestjs,Create React App,我正在使用jest和axios mock adapter测试axiosAPI调用在redux异步动作创建者中 当我使用由axios.create()创建的axios实例时,我无法使它们工作: import axios from 'axios'; const { REACT_APP_BASE_URL } = process.env; export const ajax = axios.create({ baseURL: REACT_APP_BASE_URL, }); 我会在我的异步操作创

我正在使用
jest
axios mock adapter
测试
axios
API调用在
redux
异步动作创建者中

当我使用由
axios.create()
创建的
axios
实例时,我无法使它们工作:

import axios from 'axios';

const { REACT_APP_BASE_URL } = process.env;

export const ajax = axios.create({
  baseURL: REACT_APP_BASE_URL,
});
我会在我的
异步操作创建者中使用它,比如:

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)
})
我只收到一个动作:[{“type”:“REQUEST\u TRANSACTION\u DATA”}]
,因为ajax.post出现了一个错误


我尝试了很多方法来模拟axios。在不知道我在做什么的情况下创建,但没有任何效果。非常感谢任何帮助。

好的,我知道了。下面是我如何修复它的!最后我做了而没有为
axios
制作任何模拟库

src/\uuuuu mocks\uuuu
中为
axios
创建模拟:

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

好的,我知道了。下面是我如何修复它的!最后我做了而没有为
axios
制作任何模拟库

src/\uuuuu mocks\uuuu
中为
axios
创建模拟:

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

在mockAdapter中,您正在模拟错误的实例。你应该嘲笑ajax。像这样,
constmock=MockAdapter(ajax)

这是因为您现在不是在模拟
axios
实例,而是在模拟
ajax
实例,因为它是您用来发送请求的实例,也就是说,当您执行
export const ajax=axios.create…
时,您创建了一个名为ajax的axios实例。因此,既然您在代码中执行
const result=wait ajax.post
,应该模拟axios的
ajax
实例,而不是那种情况下的
axios

在mockAdapter中,模拟的实例是错误的。你应该嘲笑ajax。像这样,
constmock=MockAdapter(ajax)

这是因为您现在不是在模拟
axios
实例,而是在模拟
ajax
实例,因为它是您用来发送请求的实例,也就是说,当您执行
export const ajax=axios.create…
时,您创建了一个名为ajax的axios实例。因此,既然您在代码中执行
const result=wait ajax.post
,应该模仿的是axios的
ajax
实例,而不是那种情况下的
axios

我有另一种解决方案

导入{
reportGet,
请求\u事务\u数据,
接收\u事务\u数据,
}来自“../redux/TransactionRedux”
从“redux模拟存储”导入configureMockStore
从“redux thunk”导入thunk
从'src/utils/apichandler'导入{END\u POINT\u MERCHANT\u TRANSACTIONS\u GET}
//从“axios”导入axios
从“..//api/ajax”//axios实例导入{ajax}
从“axios模拟适配器”导入模拟适配器
const middleware=[thunk]
const mockStore=configureMockStore(中间件)
const store=mockStore({transactions:{}})
测试('get report data',async()=>{
//让mock=新MockAdapter(axios)
让mock=newmockadapter(ajax)//这里需要模拟axios实例
常数mockData={
销售总额:0
}
mock.onPost(端点交易)。回复(200,mockData)
常数预期动作=[
{type:REQUEST\u TRANSACTION\u DATA},
{type:RECEIVE_TRANSACTION_DATA,DATA:mockData},
]
等待store.dispatch(reportGet())
expect(store.getActions()).toEqual(expectedActions)
})

我有另一个解决方案

导入{
reportGet,
请求\u事务\u数据,
接收\u事务\u数据,
}来自“../redux/TransactionRedux”
从“redux模拟存储”导入configureMockStore
从“redux thunk”导入thunk
从'src/utils/apichandler'导入{END\u POINT\u MERCHANT\u TRANSACTIONS\u GET}
//从“axios”导入axios
从“..//api/ajax”//axios实例导入{ajax}
从“axios模拟适配器”导入模拟适配器
const middleware=[thunk]
const mockStore=configureMockStore(中间件)
const store=mockStore({transactions:{}})
测试('get report data',async()=>{
//让mock=新MockAdapter(axios)
让mock=newmockadapter(ajax)//这里需要模拟axios实例
常数mockData={
销售总额:0
}
mock.onPost(端点交易)。回复(200,mockData)
常数预期动作=[
{type:REQUEST\u TRANSACTION\u DATA},
{type:RECEIVE_TRANSACTION_DATA,DATA:mockData},
]
等待store.dispatch(reportGet())
expect(store.getActions()).toEqual(expectedActions)
})

以下代码有效

   jest.mock("axios", () => {
        return {
            create: jest.fn(() => axios),
            post: jest.fn(() => Promise.resolve()),
        };
    });

下面的代码有效

   jest.mock("axios", () => {
        return {
            create: jest.fn(() => axios),
            post: jest.fn(() => Promise.resolve()),
        };
    });

如果您需要在特定测试中创建用
create
模拟
axios
Jest测试(并且不需要针对所有测试用例模拟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));
});

下面是指向相同的示例的链接,该示例不包含
创建
。区别在于添加
axios.create.mockReturnThis()

如果需要创建Jest测试,在特定测试中使用
create
模拟
axios
(并且不需要针对所有测试用例使用mock 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));
});

下面是指向相同的示例的链接,该示例不包含
创建
。区别在于添加了
axios.create.mockReturnThis()

你是我的英雄:)我知道这有点旧,但你需要返回Promise.resolve;)@ReinierKaper非常确定返回隐含在箭头函数模式中:)我一直在努力解决这个问题。我试过你的解决办法,但没用。你能看看我的特殊问题吗?谢谢建议在与节点模块相同的级别上创建uuu mocks_uuu目录,更多定义您是我的英雄:)我知道这有点旧,但您需要返回Promise.resolve;)@ReinierKaper很确定回报是显而易见的