Xior mock plugin let you easily mock requests.
Good to know: the xior mock plugin idea inspired from axios-mock-adapter
# npm
npm install xior
# pnpm
pnpm add xior
# bun
bun add xior
# yarn
yarn add xior
Basic usage:
import xior from 'xior';
import MockPlugin from 'xior/plugins/mock';
const instance = xior.create();
const mock = new MockPlugin(instance);
mock.onGet('/api/hello').reply(200, [{ msg: 'hello' }]);
instance.get('/api/hello').then((res) => {
console.log(res.data); // [{ msg: 'hello' }]
});
Using jsDelivr CDN:
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/xior.umd.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/plugins/mock.umd.js"></script>
<!-- Usage -->
<script>
const instance = xior.create();
const mock = new xiorMock(instance);
mock.onGet('/api/hello').reply(200, [{ msg: 'hello' }]);
instance.get('/api/hello').then((res) => {
console.log(res.data); // [{ msg: 'hello' }]
});
</script>
Using unpkg CDN:
<script src="https://unpkg.com/[email protected]/dist/xior.umd.js"></script>
<script src="https://unpkg.com/[email protected]/plugins/mock.umd.js"></script>
<!-- Usage -->
<script>
const instance = xior.create();
const mock = new xiorMock(instance);
mock.onGet('/api/hello').reply(200, [{ msg: 'hello' }]);
instance.get('/api/hello').then((res) => {
console.log(res.data); // [{ msg: 'hello' }]
});
</script>
DELETE
/HEAD
/OPTIONS
are same usage withGET
Mocking a GET
request:
import xior from 'xior';
import MockPlugin from 'xior/plugins/mock';
const instance = xior.create();
const mock = new MockPlugin(instance);
// Mock any GET request to /users
// arguments for reply are (status, data, headers)
mock.onGet('/users').reply(
200,
{
users: [{ id: 1, name: 'John Smith' }],
},
{
'X-Custom-Response-Header': '123',
}
);
instance.get('/users').then(function (response) {
console.log(response.data);
console.log(response.headers.get('X-Custom-Response-Header')); // 123
});
Mocking a GET
request with specific parameters:
import xior from 'xior';
import MockPlugin from 'xior/plugins/mock';
const instance = xior.create();
const mock = new MockPlugin(instance);
// Mock GET request to /users when param `searchText` is 'John'
// arguments for reply are (status, data, headers)
mock.onGet('/users', { params: { searchText: 'John' } }).reply(200, {
users: [{ id: 1, name: 'John Smith' }],
});
instance.get('/users', { params: { searchText: 'John' } }).then(function (response) {
console.log(response.data);
});
Reject all GET
requests with HTTP 500:
mock.onGet().reply(500);
PUT
/PATCH
are same usage withPOST
Mocking a POST
request:
import xior from 'xior';
import MockPlugin from 'xior/plugins/mock';
const instance = xior.create();
const mock = new MockPlugin(instance);
// Mock any POST request to /users
// arguments for reply are (status, data, headers)
mock.onPost('/users').reply(
200,
{
users: [{ id: 1, name: 'John Smith' }],
},
{
'X-Custom-Response-Header': '123',
}
);
instance.post('/users').then(function (response) {
console.log(response.data);
console.log(response.headers.get('X-Custom-Response-Header')); // 123
});
Mocking a POST
request with specific parameters and data
:
import xior from 'xior';
import MockPlugin from 'xior/plugins/mock';
const instance = xior.create();
const mock = new MockPlugin(instance);
// Mock POST request to /users when param `searchText` is 'John'
// arguments for reply are (status, data, headers)
mock.onPost('/users', null, { params: { searchText: 'John' } }).reply(200, {
users: [{ id: 1, name: 'John Smith' }],
});
instance.get('/users', null, { params: { searchText: 'John' } }).then(function (response) {
console.log(response.data);
});
Reject all POST
requests with HTTP 500:
mock.onPost().reply(500);
mock.onGet(/\/users\/\d+/).reply(function (config) {
// the actual id can be grabbed from config.url
return [200, {}];
});
Chaining is also supported:
mock.onGet('/users').reply(200, users).onGet('/posts').reply(200, posts);
.replyOnce()
can be used to let the mock only reply once:
mock
.onGet('/users')
.replyOnce(200, users) // After the first request to /users, this handler is removed
.onGet('/users')
.replyOnce(500); // The second request to /users will have status code 500
// Any following request would return a 404 since there are
// no matching handlers left
Mocking any request to a given url
// mocks GET, POST, ... requests to /foo
mock.onAny('/foo').reply(200);
.onAny
can be useful when you want to test for a specific order of requests:
// Expected order of requests:
const responses = [
['GET', '/foo', 200, { foo: 'bar' }],
['POST', '/bar', 200],
['PUT', '/baz', 200],
];
// Match ALL requests
mock.onAny().reply((config) => {
const [method, url, ...response] = responses.shift();
if (config.url === url && config.method.toUpperCase() === method) return response;
// Unexpected request, error out
return [500, {}];
});
.passThrough()
forwards the matched request over network
// Mock POST requests to /api with HTTP 201, but forward
// GET requests to server
mock
.onPost(/^\/api/)
.reply(201)
.onGet(/^\/api/)
.passThrough();
Recall that the order of handlers is significant:
// Mock specific requests, but let unmatched ones through
mock.onGet('/foo').reply(200).onPut('/bar', { xyz: 'abc' }).reply(204).onAny().passThrough();
Note that passThrough
requests are not subject to delaying by delayResponse
.
If you set onNoMatch option to passthrough
all requests would be forwarded over network by default
// Mock all requests to /foo with HTTP 200, but forward
// any others requests to server
var mock = new MockPlugin(instance, { onNoMatch: 'passthrough' });
mock.onAny('/foo').reply(200);
Using onNoMatch
option with throwException
to throw an exception when a request is made without match any handler. It's helpful to debug your test mocks.
const mock = new MockPlugin(instance, { onNoMatch: 'throwException' });
mock.onAny('/foo').reply(200);
axios.get('/unexistent-path');
// Exception message on console:
//
// Could not find mock for:
// {
// "method": "get",
// "url": "/unexistent-path"
// }
Network error:
// Returns a failed promise with Error('Network Error');
mock.onGet('/users').networkError();
// networkErrorOnce can be used to mock a network error only once
mock.onGet('/users').networkErrorOnce();
Timeout error:
// Returns a failed promise with Error `XiorTimeoutError`
mock.onGet('/users').timeout();
// timeoutOnce can be used to mock a timeout only once
mock.onGet('/users').timeoutOnce();
The history
property allows you to enumerate existing xior request objects.
The property is an object of verb keys referencing arrays of request objects.
It's useful for testing.
import xior from 'xior';
import MockPlugin from 'xior/plugins/mock';
const instance = xior.create();
const mock = new MockPlugin(instance);
describe('Feature', () => {
it('records the xior config each time the handler is invoked', function () {
mock.onAny('/foo').reply(200);
return instance.get('/foo').then(function (response) {
assert.equal(mock.history.get?.length, 1);
assert.equal(mock.history.get?.[0].method, 'GET');
assert.equal(mock.history.get?.[0].url, '/foo');
});
});
});
You can clear the history
with resetHistory
:
mock.resetHistory();
The handlers
property allows you to enumerate existing xior response objects.
It's useful for testing.
import xior from 'xior';
import MockPlugin from 'xior/plugins/mock';
const instance = xior.create();
const mock = new MockPlugin(instance);
describe('Feature', () => {
it('resets the registered mock handlers', function () {
mock.onGet('/foo').reply(200);
assert.equal(mock.handlers['get'] && mock.handlers['get'].length > 0, true);
mock.reset();
assert.equal(mock.handlers['get'], undefined);
});
});
You can clear the handlers
with resetHandlers
:
mock.resetHandlers();
import xior from 'xior';
import MockPlugin from 'xior/plugins/mock';
const instance = xior.create();
const mock = new MockPlugin(instance);
// reset history
mock.resetHistory();
// reset handlers
mock.resetHandlers();
// reset history and handlers
mock.reset();
// remove the mock plugin from instance
mock.restore();