模拟内部 axios.create()
Posted
技术标签:
【中文标题】模拟内部 axios.create()【英文标题】:Mock inner 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
无济于事,但我并不真正知道我在做什么。感谢任何帮助。
【问题讨论】:
【参考方案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()的主要内容,如果未能解决你的问题,请参考以下文章