原文链接:https://github.com/ctimmerm/axios-mock-adapter
Axios适配器,允许轻松模拟请求
安装
使用npm:
$ npm install axios-mock-adapter --save-dev
它也可用作UMD版本:
- https://unpkg.com/axios-mock-adapter/dist/axios-mock-adapter.js
- https://unpkg.com/axios-mock-adapter/dist/axios-mock-adapter.min.js
axios-mock-adapter适用于Node和浏览器,适用于axios v0.9.0及更高版本。
案例
模拟GET
请求
var axios = require('axios');
var MockAdapter = require('axios-mock-adapter');
// 这将模拟适配器设置为默认实例
var mock = new MockAdapter(axios);
// 将任何GET请求模拟到 /users
// 用于回复的参数是(status,data,headers)
mock.onGet('/users').reply(200, {
users: [
{ id: 1, name: 'John Smith' }
]
});
axios.get('/users')
.then(function(response) {
console.log(response.data);
});
模拟GET
使用特定参数请求
var axios = require('axios');
var MockAdapter = require('axios-mock-adapter');
// 这将模拟适配器设置为默认实例
var mock = new MockAdapter(axios);
// 当param`searchText`为'John'时,向 /users使用Mock GET请求
// 回复的参数是(status,data,headers)
mock.onGet('/users', { params: { searchText: 'John' } }).reply(200, {
users: [
{ id: 1, name: 'John Smith' }
]
});
axios.get('/users', { params: { searchText: 'John' } } )
.then(function(response) {
console.log(response.data);
});
要为响应添加延迟,请在实例化适配器时指定延迟量(以毫秒为单位)
//使用此实例的所有请求都将延迟2秒:
var mock = new MockAdapter(axiosInstance, { delayResponse: 2000 });
您可以恢复原始适配器(这将删除模拟行为)
mock.restore();
您还可以使用重置已注册的模拟处理程序 resetHandlers
mock.resetHandlers();
您可以使用重置已注册的模拟处理程序和历史记录项 reset
mock.reset();
reset
不同于restore的地方
在于restore
完全去除的axios实例的mocking,而reset
只有消除了所增加与使用onGET,onPOST等,等所有的模拟处理,但留下mocking到位。
模拟低级网络错误
// 返回带有错误的失败promise ('Network Error');
mock.onGet('/users').networkError();
//networkErrorOnce可以用来模拟网络错误只有一次
mock.onGet('/users').networkErrorOnce();
模拟网络超时
// 返回与设置为“ECONNABORTED”代码错误失败的promise
mock.onGet('/users').timeout();
// timeoutOnce只能用于模拟一次模拟超时
mock.onGet('/users').timeoutOnce();
将功能传递给 reply
mock.onGet('/users').reply(function(config) {
//`config`是axios配置,包含url之类的东西
// 以[status,data,headers]的形式返回数组
return [200, {
users: [
{ id: 1, name: 'John Smith' }
]
}];
});
将函数传递给reply
它会返回一个axios请求,主要是模拟重定向
mock.onPost('/foo').reply(function(config) {
return axios.get('/bar');
});
使用正则表达式
mock.onGet(/\/users\/\d+/).reply(function(config) {
// 可以从config.url中获取实际id
return [200, {}];
});
在正则表达式中使用变量
const usersUri = '/users';
const url = new RegExp(`${usersUri}/*`);
mock.onGet(url).reply(200, users);
仅通过动词指定不匹配的路径
// Reject all POST requests with HTTP 500
mock.onPost().reply(500);
链接也受支持
mock
.onGet('/users').reply(200, users)
.onGet('/posts').reply(200, posts);
.replyOnce()
可以用来让mock只回复一次
mock
.onGet('/users').replyOnce(200, users) // 第一次请求 /users后,这个此处理程序会被删除
.onGet('/users').replyOnce(500); // 对/users的第二个请求将具有状态代码500
// 任何后续请求都将返回404,因为没有匹配的处理程序
将任何请求模拟到给定的URL
// 模拟GET,POST,...请求/foo
mock.onAny('/foo').reply(200);
.onAny
当您想要测试特定的请求顺序时,它会很有用
// 预期的请求顺序:
const responses = [
['GET', '/foo', 200, { foo: 'bar' }],
['POST', '/bar', 200],
['PUT', '/baz', 200]
];
// //匹配所有模拟请求
mock.onAny().reply(config => {
const [method, url, ...response] = responses.shift();
if (config.url === url && config.method.toUpperCase() === method) return response;
//意想不到的请求,错误输出
return [500, {}];
});
使用HTTP 404响应拒绝不映射到模拟处理程序的请求。由于处理程序按顺序匹配,onAny()
因此可以使用final 来更改默认行为
// Mock GET请求 /foo,拒绝所有其他人使用HTTP 500
mock
.onGet('/foo').reply(200)
.onAny().reply(500);
使用特定请求正文/数据模拟请求
mock.onPut('/product', { id: 4, name: 'foo' }).reply(204);
.passThrough()
通过网络转发匹配的请求
// Mock POST requests to /api with HTTP 201, but forward
// GET requests to server
mock
.onPost(/\/^api/).reply(201)
.onGet(/\/^api/).passThrough();
回想一下处理程序的顺序很重要
// Mock specific requests, but let unmatched ones through
mock
.onGet('/foo').reply(200)
.onPut('/bar', { xyz: 'abc' }).reply(204)
.onAny().passThrough();
请注意,passThrough
请求不会延迟delayResponse
。
从1.7.0开始,reply
函数可能会返回一个Promise:
mock.onGet('/product').reply(function(config) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
if (Math.random() > 0.1) {
resolve([200, { id: 4, name: 'foo' } ]);
} else {
// reject() reason will be passed as-is.
// Use HTTP error status code to simulate server failure.
resolve([500, { success: false } ]);
}
}, 1000);
});
});
使用Promises从多个来源编写:
var normalAxios = axios.create();
var mockAxios = axios.create();
var mock = new MockAdapter(mockAxios);
mock
.onGet('/orders')
.reply(() => Promise.all([
normalAxios
.get('/api/v1/orders')
.then(resp => resp.data),
normalAxios
.get('/api/v2/orders')
.then(resp => resp.data),
{ id: '-1', content: 'extra row 1' },
{ id: '-2', content: 'extra row 2' }
]).then(
sources => [200, sources.reduce((agg, source) => agg.concat(source))]
)
);
历史
该history
属性允许您枚举现有的axios请求对象。该属性是动词键的对象,引用请求对象的数组。
这对测试很有用。
describe('Feature', () => {
it('requests an endpoint', (done) => {
var mock = new AxiosMockAdapter(axios);
mock.onPost('/endpoint').replyOnce(200);
feature.request()
.then(() => {
expect(mock.history.post.length).toBe(1);
expect(mock.history.post[0].data).toBe(JSON.stringify({ foo: 'bar' }));
})
.then(done)
.catch(done.fail);
});
});
您可以清除历史记录 resetHistory
mock.resetHistory();