模拟内部 axios.create()

Posted

技术标签:

【中文标题】模拟内部 axios.create()【英文标题】:Mock inner axios.create() 【发布时间】:2018-12-25 21:32:43 【问题描述】:

我正在使用 jestaxios-mock-adapter 来测试 axios 异步操作创建者中的 axios API 调用。

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

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 无济于事,但我并不真正知道我在做什么。感谢任何帮助。

【问题讨论】:

【参考方案1】:

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

src/__mocks__ 中为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)
)

【讨论】:

你是我的英雄 :) 我知道这有点旧,但你需要返回 Promise.resolve ;) @ReinierKaper 很确定返回隐含在该箭头函数模式中:) 我一直在努力解决这个问题。我尝试了您的解决方案,但没有奏效。你能看看我的具体问题吗?谢谢! ***.com/questions/60745903/… 建议在node_modules同级创建__mocks__目录,更多定义here【参考方案2】:

如果您需要创建 Jest 测试,该测试在特定测试中使用 create 模拟 axios(并且不需要所有测试用例的模拟 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 mocking in Jest 的相同示例的链接。不同的是要加axios.create.mockReturnThis()

【讨论】:

试试这个,我得到TypeError: axios.create.mockReturnThis is not a function 只要在模拟运行之前不调用 axios.create 就可以完美运行。很好谢谢。 @mikemaccana 在这种情况下,我会确保您正确地模拟 axios,如第二行所示【参考方案3】:

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

【讨论】:

【参考方案4】:

我有另一个解决方案。

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

【讨论】:

【参考方案5】:

这是我对 axios 的模拟

export default 
    defaults:
        headers:
            common:
                "Content-Type":"",
                "Authorization":""
            
        
  ,
  get: jest.fn(() => Promise.resolve( data:  )),
  post: jest.fn(() => Promise.resolve( data:  )),
  put: jest.fn(() => Promise.resolve( data:  )),
  delete: jest.fn(() => Promise.resolve( data:  )),
  create: jest.fn(function () 
      return 
          interceptors:
              request :   
                  use: jest.fn(() => Promise.resolve( data:  )),
              
          ,

          defaults:
                headers:
                    common:
                        "Content-Type":"",
                        "Authorization":""
                    
                
          ,
          get: jest.fn(() => Promise.resolve( data:  )),
          post: jest.fn(() => Promise.resolve( data:  )),
          put: jest.fn(() => Promise.resolve( data:  )),
          delete: jest.fn(() => Promise.resolve( data:  )),
      
  ),
;

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案6】:

以下代码有效!

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

【讨论】:

只需要导入import axios from 'axios'

以上是关于模拟内部 axios.create()的主要内容,如果未能解决你的问题,请参考以下文章

MockjsReact + Mockjs 模拟接口

MockjsReact + Mockjs 模拟接口

使用 STM32L422 上的内部参考电压测量模拟值

如何使用 Mockito 模拟内部类实例

Jest 模拟内部函数

模拟另一个类方法的内部调用