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

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

【问题讨论】:

    标签: javascript reactjs axios jestjs create-react-app


    【解决方案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 很确定返回隐含在该箭头函数模式中:)
    • 我一直在努力解决这个问题。我尝试了您的解决方案,但没有奏效。你能看看我的具体问题吗?谢谢! stackoverflow.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'
        猜你喜欢
        • 2020-05-26
        • 1970-01-01
        • 2022-12-30
        • 1970-01-01
        • 2021-09-07
        • 2015-11-20
        • 2018-12-18
        • 1970-01-01
        相关资源
        最近更新 更多