Product
Introducing Ruby Support in Socket
Socket is launching Ruby support for all users. Enhance your Rails projects with AI-powered security scans for vulnerabilities and supply chain threats. Now in Beta!
fetch-mock
Advanced tools
fetch-mock is a library for mocking HTTP requests made using the Fetch API. It allows developers to simulate different responses and behaviors for fetch calls, which is particularly useful for testing and development purposes.
Mocking a simple GET request
This feature allows you to mock a simple GET request. The code sample demonstrates how to mock a GET request to 'https://api.example.com/data' and return a JSON object with sample data.
const fetchMock = require('fetch-mock');
fetchMock.get('https://api.example.com/data', { data: 'sample data' });
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data));
Mocking a POST request with specific body
This feature allows you to mock a POST request with a specific request body. The code sample demonstrates how to mock a POST request to 'https://api.example.com/submit' and return different responses based on the request body.
const fetchMock = require('fetch-mock');
fetchMock.post('https://api.example.com/submit', (url, options) => {
if (options.body === JSON.stringify({ key: 'value' })) {
return { status: 'success' };
} else {
return { status: 'error' };
}
});
fetch('https://api.example.com/submit', {
method: 'POST',
body: JSON.stringify({ key: 'value' })
})
.then(response => response.json())
.then(data => console.log(data));
Mocking with delay
This feature allows you to mock a request with a delay. The code sample demonstrates how to mock a GET request to 'https://api.example.com/delayed' and return a response after a 1-second delay.
const fetchMock = require('fetch-mock');
fetchMock.get('https://api.example.com/delayed', new Promise(resolve => setTimeout(() => resolve({ data: 'delayed data' }), 1000)));
fetch('https://api.example.com/delayed')
.then(response => response.json())
.then(data => console.log(data));
Mocking with different response statuses
This feature allows you to mock requests with different HTTP response statuses. The code sample demonstrates how to mock a GET request to 'https://api.example.com/not-found' and return a 404 status.
const fetchMock = require('fetch-mock');
fetchMock.get('https://api.example.com/not-found', 404);
fetch('https://api.example.com/not-found')
.then(response => {
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
})
.catch(error => console.error('Fetch error:', error));
Nock is a HTTP mocking and expectations library for Node.js. It intercepts HTTP requests and allows you to define custom responses. Compared to fetch-mock, Nock is more focused on Node.js and works with any HTTP library, not just fetch.
Mock Service Worker (MSW) is a library for mocking network requests in both browser and Node.js environments. It uses Service Workers to intercept requests in the browser, making it more versatile for front-end testing compared to fetch-mock.
Axios Mock Adapter is a library specifically designed for mocking requests made with the Axios HTTP client. It provides a simple API for defining request handlers and responses. While fetch-mock is designed for the Fetch API, axios-mock-adapter is tailored for Axios.
Mock http requests made using fetch (or isomorphic-fetch). As well as shorthand methods for the simplest use cases, it offers a flexible API for customising mocking behaviour, and can also be persisted (with resettable state) over a series of tests.
npm install fetch-mock
then require('fetch-mock')
in most environments
To output useful messages for debugging export DEBUG=fetch-mock
require('fetch-mock')
exports a singleton with the following methods
mock(matcher, response)
or mock(matcher, method, response)
Replaces fetch()
with a stub which records it's calls, grouped by route, and optionally returns a mocked Response
object or passes the call through to fetch()
. Calls to .mock()
can be chained.
matcher
[required]: Condition for selecting which requests to mock Accepts any of the following
string
: Either an exact url to match e.g. 'http://www.site.com/page.html' or, if the string begins with a ^
, the string following the ^
must begin the url e.g. '^http://www.site.com' would match 'http://www.site.com' or 'http://www.site.com/page.html'RegExp
: A regular expression to test the url againstFunction(url, opts)
: A function (returning a Boolean) that is passed the url and opts fetch()
is called with (or, if fetch()
was called with one, the Request
instance)method
[optional]: only matches requests using this http methodresponse
[required]: Configures the http response returned by the mock. Can take any of the following values
number
: Creates a response with this statusstring
: Creates a 200 response with the string as the response bodyobject
: As long as the object does not contain any of the properties below it is converted into a json string and returned as the body of a 200 response. If any of the properties below are defined it is used to configure a Response
object
body
: Set the response body (string
or object
)status
: Set the response status (defaut 200
)headers
: Set the response headers. (object
)throws
: If this property is present then a Promise
rejected with the value of throws
is returnedFunction(url, opts)
: A function that is passed the url and opts fetch()
is called with and that returns any of the responses listed aboveconst fetchMock = require('fetch-mock');
fetchMock
.mock('http://domain1', 200)
.mock('http://domain2', 'DELETE', 204);
restore()
Restores fetch()
to its unstubbed state and clears all data recorded for its calls
reMock()
Calls restore()
internally then calls mock()
. This allows you to put some generic calls to mock()
in a beforeEach()
while retaining the flexibility to vary the responses for some tests
reset()
Clears all data recorded for fetch()
's calls
calls(matcher)
Returns an object {matched: [], unmatched: []}
containing arrays of all calls to fetch, grouped by whether fetch-mock matched them or not. If matcher
is specified and is equal to matcher.toString()
for any of the mocked routes then only calls to fetch matching that route are returned.
called(matcher)
Returns a Boolean indicating whether fetch was called and a route was matched. If matcher
is specified and is equal to matcher.toString()
for any of the mocked routes then only returns true
if that particular route was matched.
mock(routeConfig)
Use a configuration object to define a route to mock.
name
[optional]: A unique string naming the route. Used to subsequently retrieve references to the calls, grouped by name. If not specified defaults to matcher.toString()
method
[optional]: http methodmatcher
[required]: as specified aboveresponse
[required]: as specified abovemock(routes)
Pass in an array of route configuration objects
mock(config)
Pas in an object containing more complex config for fine grained control over every aspect of mocking behaviour. May have the following properties
routes
: Either a single route config object or an array of them (see above)responses
: When registerRoute()
(see below) has already been used to register some routes then responses
can be used to override the default response. Its value should be an object mapping route names to responses, which should be similar to those provided in the response
property of stanadard route configurations e.g. responses: {
session: function (url, opts) {
if (opts.headers.authorized) {
return {user: 'dummy-authorized-user'};
} else {
return {user: 'dummy-unauthorized-user'};
}
}
}
greed
: Determines how the mock handles unmatched requests
fetch()
calls(routeName)
Returns an array of arrays of the arguments passed to fetch()
that matched the given route.
called(routeName)
Returns a Boolean denoting whether any calls matched the given route.
registerRoute()
Often your application/module will need a mocked response for some http requests in order to initialise properly, even if the content of those calls are not the subject of a given test e.g. a mock response from an authentication service and a multi-variant testing service might be necessary in order to test the UI for a version of a log in form. It's helpful to be able to define some default responses for these services which will exist throughout all or a large subset of your tests. registerRoute()
aims to fulfil this need. All these predefined routes can be overridden when mock(config)
is called.
registerRoute(object)
: An object similar to the route objects accepted by mock()
registerRoute(array)
: An array of the above objectsregisterRoute(name, matcher, response)
: The 3 properties of the route object spread across 3 parametersunregisterRoute(name)
Unregisters one or more previously registered routes. Accepts either a string or an array of strings
useNonGlobalFetch(func)
When using isomorphic-fetch or node-fetch ideally fetch
should be added as a global. If not possible to do so you can still use fetch-mock in combination with mockery in nodejs. To use fetch-mock with with mockery you will need to use this function to prevent fetch-mock trying to mock the function globally.
func
Optional reference to fetch
(or any other function you may want to substitute for fetch
in your tests).To obtain a reference to the mock fetch call getMock()
.
var fetch = require('node-fetch');
var fetchMock = require('fetch-mock');
var mockery = require('mockery');
fetchMock.useNonGlobalFetch(fetch);
fetchMock.registerRoute([
...
])
it('should make a request', function (done) {
mockery.registerMock('fetch', fetchMock.mock().getMock());
// test code goes in here
mockery.deregisterMock('fetch');
done();
});
require('fetch-mock/es5/client')
.node_modules/fetch-mock/es5/client-browserified.js
in a script tag. This loads fetch-mock into the fetchMock
global variable.require('fetch-mock/es5/server')
require('isomorphic-fetch')
before any of your tests.require('isomorphic-fetch')
can also be used, but it may be easier to npm install whatwg-fetch
(the module isomorphic-fetch is built around) and load ./node_modules/whatwg-fetch/fetch.js
directly into the page, either in a script tag or by referencing it your test runner config
var fetchMock = require('fetch-mock');
// Simplest use case
it('should pretend to be Rambo', done => {
fetchMock.mock('http://rambo.was.ere', 301);
fetch('http://rambo.was.ere')
.then(res => {
expect(fetchMock.calls().matched.length).to.equal(1);
expect(res.status).to.equal(301);
fetchMock.restore();
done();
});
})
// Optionally set up some routes you will always want to mock
// Accepts an array of config objects or three parameters,
// name, matcher and response, to add a single route
fetchMock.registerRoute([
{
name: 'session',
matcher: 'https://sessionservice.host.com',
response: {
body: 'user-12345',
// opts is as expected by https://github.com/bitinn/node-fetch/blob/master/lib/response.js
// headers should be passed as an object literal (fetch-mock will convert it into a Headers instance)
// status defaults to 200
opts: {
headers: {
'x-status': 'unsubscribed'
},
status: 401
}
}
},
{
name: 'geo',
matcher: /^https\:\/\/geoservice\.host\.com/,
// objects will be converted to strings using JSON.stringify before being returned
response: {
body: {
country: 'uk'
}
}
}
])
it('should do A', function () {
fetchMock.mock({
// none: all unmatched calls get sent straight through to the default fetch
// bad: all unmatched calls result in a rejected promise
// good: all unmatched calls result in a resolved promise with a 200 status
greed: 'none'
});
thingToTest.exec();
// returns an array of calls to the session service,
// each item in the array is an array of the arguments passed to fetch
// similar to sinon.spy.args
fetchMock.calls('session') // non empty array
fetchMock.called('geo') // Boolean
// reset all call logs
fetchMock.reset()
fetchMock.calls('session') // undefined
fetchMock.called('geo') // false
// fetch itself is just an ordinary sinon.stub
fetch.calledWith('thing')
// restores fetch and resets all data
fetchMock.restore();
})
describe('content', function () {
before(function () {
// register an additional route, this one has a more complex matching rule
fetchMock.registerRoute('content', function (url, opts) {
return opts.headers.get('x-api-key') && url.test(/^https\:\/\/contentservice\.host\.com/);
}, {body: 'I am an article'});
});
after(function () {
fetchMock.unregisterRoute('content');
})
it('should do B', function () {
fetchMock.mock({
// you can choose to mock a subset of the registered routes
// and even add one to be mocked for this test only
// - the route will exist until fetchMock.restore() is called
routes: ['session', 'content', {
name: 'enhanced-content',
matcher: /^https\:\/\/enhanced-contentservice\.host\.com/,
// responses can be contextual depending on the request
// url and opts parameters are exactly what would be passed to fetch
response: function (url, opts) {
return {body: 'enhanced-article-' + url.split('article-id/')[1]};
}
}]
});
thingToTest.exec();
fetchMock.calls('content') // non empty array
fetchMock.called('enhanced-content') // Boolean
// restores fetch and resets all data
fetchMock.restore();
})
it('should do C', function () {
fetchMock.mock({
// you can override the response for a service for this test only
// this means e.g. you can configure an authentication service to return
// a valid user normally, but only return invalid for the one test
// where you're testing authentication
responses: {
'session': 'invalid-user'
}
});
thingToTest.exec();
// restores fetch and resets all data
fetchMock.restore();
})
});
FAQs
Mock http requests made using fetch
The npm package fetch-mock receives a total of 670,924 weekly downloads. As such, fetch-mock popularity was classified as popular.
We found that fetch-mock demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket is launching Ruby support for all users. Enhance your Rails projects with AI-powered security scans for vulnerabilities and supply chain threats. Now in Beta!
Product
Ensure open-source compliance with Socket’s License Enforcement Beta. Set up your License Policy and secure your software!
Product
We're launching a new set of license analysis and compliance features for analyzing, managing, and complying with licenses across a range of supported languages and ecosystems.