Introduction
fetch-mock allows mocking http requests made using fetch or a library imitating its api, such as node-fetch or fetch-ponyfill.
It supports most JavaScript environments, including Node.js, web workers, service workers, and any browser that either supports fetch
natively or that can have a fetch
polyfill installed.
As well as shorthand methods for the simplest use cases, it offers a flexible API for customising all aspects of mocking behaviour.
fetchMock.mock('http://example.com', 200);
const res = await fetch('http://example.com');
assert(res.ok);
fetchMock.restore();
Quickstart
Setting up your mock
- The commonest use case is
fetchMock.mock(matcher, response)
, wherematcher
is an exact url or regex to match, andresponse
is a status code, string or object literal. - You can also use
fetchMock.once()
to limit to a single call orfetchMock.get()
,fetchMock.post()
etc. to limit to a method. - All these methods are chainable so you can easily define several mocks in a single test.
fetchMock
.get('http://good.com/', 200)
.post('http://good.com/', 400)
.get(/bad\.com/, 500)
Analysing calls to your mock
fetchMock.called(matcher)
reports if any calls matched your mock (or leavematcher
out if you just want to checkfetch
was called at all).fetchMock.lastCall()
,fetchMock.lastUrl()
orfetchMock.lastOptions()
give you access to the parameters last passed in tofetch
.fetchMock.done()
will tell you iffetch
was called the expected number of times.
Tearing down your mock
fetchMock.resetHistory()
resets the call history.fetchMock.reset()
orfetchMock.restore()
will also restorefetch()
to its native implementation
Example
Example with Node.js: suppose we have a file make-request.js
with a function that calls fetch
:
require('isomorphic-fetch');
module.exports = function makeRequest() {
return fetch('http://httpbin.org/my-url', {
headers: {
user: 'me'
}
}).then(function(response) {
return response.json();
});
};
We can use fetch-mock to mock fetch
. In mocked.js
:
var makeRequest = require('./make-request');
var fetchMock = require('fetch-mock');
// Mock the fetch() global to return a response
fetchMock.get('http://httpbin.org/my-url', { hello: 'world' }, {
delay: 1000, // fake a slow network
headers: {
user: 'me' // only match requests with certain headers
}
});
makeRequest().then(function(data) {
console.log('got data', data);
});
// Unmock.
fetchMock.reset();
Result:
$ node mocked.js
'got data' { hello: 'world' }
Previous versions
v7, v8 & v9 are practically identical, only differing in their treatment of a few edge cases, or in compatibility with other libraries and environments. For clarity, each section of the documentation tells you which version a feature was added with a version label.
For previous versions follow the documentation below:
Usage
Requirements
fetch-mock requires the following to run:
- Node.js 8+ for full feature operation
- Node.js 0.12+ with limitations
- npm (normally comes with Node.js)
- Either
- node-fetch when testing in Node.js. To allow users a choice over which version to use,
node-fetch
is not included as a dependency offetch-mock
. - A browser that supports the
fetch
API either natively or via a polyfill/ponyfill
- node-fetch when testing in Node.js. To allow users a choice over which version to use,
Check out the new cheatsheet
Installation
Install fetch-mock using
npm install --save-dev fetch-mock
fetch-mock supports both ES modules and commonjs. The following should work in most environments. Check the importing the correct version section of the docs if you experience problems.
ES modules
import fetchMock from 'fetch-mock';
Commonjs
const fetchMock = require('fetch-mock');
Global or non-global
fetch
can be used by your code globally or locally. It’s important to determine which one applies to your codebase as it will impact how you use fetch-mock
Global fetch
In the following scenarios fetch
will be a global
- When using native
fetch
(or a polyfill) in the browser - When
node-fetch
has been assigned toglobal
in your Node.js process (a pattern sometimes used in isomorphic codebases)
By default fetch-mock assumes fetch
is a global so no more setup is required once you’ve required fetch-mock
.
Non-global fetch library
In the following scenarios fetch
will not be a global
- Using node-fetch in Node.js without assigning to
global
- Using fetch-ponyfill in the browser
- Using libraries which use fetch-ponyfill internally
- Some build setups result in a non-global
fetch
, though it may not always be obvious that this is the case
The sandbox()
method returns a function that can be used as a drop-in replacement for fetch
. Pass this into your mocking library of choice. The function returned by sandbox()
has all the methods of fetch-mock
exposed on it, e.g.
const fetchMock = require('fetch-mock');
const myMock = fetchMock.sandbox().mock('/home', 200);
// pass myMock in to your application code, instead of fetch, run it, then...
expect(myMock.called('/home')).to.be.true;
Importing the correct version
The JS ecosystem is in a transitional period between module systems, and there are also a number of different build tools available, all with their own idosyncratic opinions about how JS should be compiled. The following detail may help debug any problems, and a few known workarounds are listed below.
Built files
In general server
refers to the version of the source code designed for running in nodejs, whereas client
refers to the version designed to run in the browser. As well as this distinction, fetch-mock builds several versions of itself:
/cjs
directory - this contains a copy of the source files (which are currently written as commonjs modules). They are copied here in order to prevent direct requires from/src
, which could make migrating the src to ES modules troublesome.client.js
andserver.js
are the entry points. The directory also contains apackage.json
file specifying that the directory contains commonjs modules./esm
directory - This contains builds of fetch-mock, exported as ES modules.client.js
andserver.js
are the entry points. The bundling tool used is rollup./es5
directory - This contains builds of fetch-mock which do not use any JS syntax not included in the ES5 standard, i.e. excludes recent additions to the language. It contains 4 entry points:client.js
andserver.js
, both of which are commonjs modulesclient-legacy.js
, which is the same asclient.js
, but includes some babel polyfill bootstrapping to ease running it in older environmentsclient-bundle.js
,client-legacy-bundle.js
, which are standalone UMD bundles of the es5 client code that can be included in the browser using an ordinary script tag. The bundling tool used is rollup.
Importing the right file
The package.json file references a selection of the above built files:
{
"main": "./cjs/server.js",
"browser": "./esm/client.js",
"module": "./esm/server.js",
}
These are intended to target the most common use cases at the moment:
- nodejs using commonjs
- nodejs using ES modules
- bundling tools such as webpack
In most cases, your environment & tooling will use the config in package.json to import the correct file when you import
or require
fetch-mock
by its name only.
However, import
/require
will sometimes get it wrong. Below are a few scenarios where you may need to directly reference a different entry point.
- If your client-side code or tests do not use a loader that respects the
browser
field ofpackage.json
userequire('fetch-mock/es5/client')
orimport fetchMock from 'fetch-mock/esm/client'
. - When not using any bundler in the browser, use one of the following as the src of a script tag:
node_modules/fetch-mock/es5/client-bundle.js
,node_modules/fetch-mock/es5/client-legacy-bundle.js
. This loads fetch-mock into thefetchMock
global variable. - For Node.js 6 or lower use
require('fetch-mock/es5/server')
Polyfilling fetch
Many older browsers require polyfilling the fetch
global. The following approaches can be used:
-
Add the following polyfill.io script to your test page
<script src="https://polyfill.io/v2/polyfill?features=fetch"></script>
-
npm install whatwg-fetch
and load./node_modules/whatwg-fetch/fetch.js
into the page, either in a script tag or by referencing in your test runner config.
Custom subclasses v5.9.0
fetch-mock
uses Request
, Response
and Headers
constructors internally, and obtains these from node-fetch
in Node.js, or window
in the browser. If you are using an alternative implementation of fetch
you will need to configure fetch-mock
to use its implementations of these constructors instead. These should be set on the fetchMock.config
object, e.g.
const ponyfill = require('fetch-ponyfill')();
Object.assign(fetchMock.config, {
Headers: ponyfill.Headers,
Request: ponyfill.Request,
Response: ponyfill.Response,
fetch: ponyfill
})
Usage with Jest
Please try out the new jest-friendly wrapper for fetch-mock, fetch-mock-jest, and feedback
Jest has rapidly become a very popular, full-featured testing library. Usage of fetch-mock with Jest is sufficiently different to previous libraries that it deserves some examples of its own:
If using global fetch
, then no special treatment is required.
For non-global uses of node-fetch
use something like:
jest.mock('node-fetch', () => require('fetch-mock').sandbox())
if you need to fallback to the network (or have some other use case for giving fetch-mock
access to node-fetch
internals you will need to use jest.requireActual('node-fetch')
, e.g.
jest.mock('node-fetch', () => {
const nodeFetch = jest.requireActual('node-fetch');
const fetchMock = require('fetch-mock').sandbox();
Object.assign(fetchMock.config, {
fetch: nodeFetch
});
return fetchMock;
})
The content of the above function (exporting fetchMock
) can also be used in a manual mock.
Once mocked, you should require node-fetch
, not fetch-mock
, in your test files - all the fetch-mock
methods will be available on it.
When using a webpack based compilation step, something like the following may be necessary instead
const fetchMock = require('fetch-mock').sandbox();
const nodeFetch = require('node-fetch');
nodeFetch.default = fetchMock;
Configuration v6.0.0
On any fetch-mock
instance, set configuration options directly on the fetchMock.config
object. e.g.
const fetchMock = require('fetch-mock');
fetchMock.config.sendAsJson = false;
Options
-
sendAsJson†
v4.1.0
Boolean
[defaulttrue
] -
Always convert objects passed to
.mock()
to JSON strings before building reponses. Can be useful to set tofalse
globally if e.g. dealing with a lot ofArrayBuffer
s. Whentrue
theContent-Type: application/json
header will also be set on each response. -
includeContentLength†
v5.13.0
Boolean
[defaulttrue
] -
Sets a
Content-Length
header on each response. -
fallbackToNetwork
v6.5.0
Boolean
|String
[defaultfalse
] -
true
: Unhandled calls fall through to the networkfalse
: Unhandled calls throw an error'always'
: All calls fall through to the network, effectively disabling fetch-mock.
-
overwriteRoutes†
v6.0.0
Boolean
[defaultundefined
] -
Configures behaviour when attempting to add a new route with the same name (or inferred name) as an existing one
undefined
: An error will be throwntrue
: Overwrites the existing routefalse
: Appends the new route to the list of routes
-
matchPartialBody
v9.1.0
Boolean
-
Match calls that only partially match a specified body json. Uses the is-subset library under the hood, which implements behaviour the same as jest’s .objectContainig() method.
-
warnOnFallback
v6.0.0
Boolean
[defaulttrue
] -
Print a warning if any call is caught by a fallback handler (set using
catch()
,spy()
or thefallbackToNetwork
option) -
Promise
v5.9.0
Constructor
-
A custom
Promise
constructor, if your application uses one -
fetch
Function
-
A custom
fetch
implementation, if your application uses one -
Headers
v5.9.0
Constructor
-
The
Headers
constructor of a customfetch
implementation, if your application uses one -
Request
v5.9.0
Constructor
-
The
Request
constructor of a customfetch
implementation, if your application uses one -
Response
v5.0.0
Constructor
-
The
Response
constructor of a customfetch
implementation, if your application uses one
Options marked with a †
can also be overridden for individual calls to .mock(matcher, response, options)
by setting as properties on the options
parameter
Debugging
The first step when debugging tests should be to run with the environment variable DEBUG=fetch-mock*
. This will output additional logs for debugging purposes.
Mocking API
.mock(matcher, response, options) v2.0.0
Check out the new cheatsheet
Initialises or extends a stub implementation of fetch, applying a route
that matches matcher
, delivers a Response
configured using response
, and that respects the additional options
. The stub will record its calls so they can be inspected later. If .mock
is called on the top level fetch-mock
instance, this stub function will also replace fetch
globally. Calling .mock()
with no arguments will carry out this stubbing without defining any mock responses.
In the documentation, route is often used to refer to the combination of matching and responding behaviour set up using a single call to mock()
Parameters
-
matcher
v2.0.0
String
|Regex
|Function
|Object
-
Criteria for which calls to
fetch
should match this route -
response
v2.0.0
String
|Object
|Function
|Promise
|Response
-
Response to send when a call is matched
-
options
v2.0.0
Object
-
More options to configure matching and responding behaviour
Alternatively a single parameter, options
, an Object with matcher
, response
and other options defined, can be passed in.
For complex matching (e.g. matching on headers in addition to url), there are 4 patterns to choose from:
- Use an object as the first argument, e.g.
fetchMock .mock({url, headers}, response)
This has the advantage of keeping all the matching criteria in one place.
- Pass in options in a third parameter e.g.
fetchMock .mock(url, response, {headers})
This splits matching criteria between two parameters, which is arguably harder to read. However, if most of your tests only match on url, then this provides a convenient way to create a variant of an existing test.
- Use a single object, e.g.
fetchMock .mock({url, response, headers})
Nothing wrong with doing this, but keeping response configuration in a separate argument to the matcher config feels like a good split.
- Use a function matcher e.g.
fetchMock .mock((url, options) => { // write your own logic }, response)
Avoid using this unless you need to match on some criteria fetch-mock does not support.
fetchMock
.mock('http://it.at.here/route', 200)
.mock('begin:http://it', 200)
.mock('end:here/route', 200)
.mock('path:/route', 200)
.mock('*', 200)
fetchMock
.mock(/.*\.here.*/, 200)
.mock((url, opts) => opts.method === 'patch', 200)
.mock('express:/:type/:id', 200, {
params: {
type: 'shoe'
}
})
.mock({
headers: {'Authorization': 'Bearer 123'},
method: 'POST'
}, 200)
fetchMock
.mock('*', 'ok')
.mock('*', 404)
.mock('*', {results: []})
.mock('*', {throw: new Error('Bad kitty')))
.mock('*', new Promise(res => setTimeout(res, 1000, 404)))
.mock('*', (url, opts) => {
status: 302,
headers: {
Location: url.replace(/^http/, 'https')
},
}))
fetchMock
.mock('begin:http://it.at.here/api', 403)
.mock({
url: 'begin:http://it.at.here/api',
headers: {
authorization: 'Basic dummy-token'
}
}, 200)
callApi('/endpoint', 'dummy-token')
.then(res => {
expect(res.status).to.equal(200)
})
matcher parameter for mock() v1.0.0
String
|
RegExp
|
Function
|
URL
|
Object
Criteria for deciding which requests to mock.
Note that if you use matchers that target anything other than the url string, you may also need to add a name
to your matcher object so that a) you can add multiple mocks on the same url that differ only in other properties (e.g. query strings or headers) b) if you inspect the result of the fetch calls, retrieving the correct results will be easier.
Argument values
-
*
v5.0.0
String
-
Match any url
"*"
-
url
v1.0.0
String
|URL
-
Match an exact url. Can be defined using a string or a
URL
instance"http://www.site.com/page.html"
-
begin:...
v5.7.0
String
-
Match a url beginning with a string
"begin:http://www.site.com"
-
end:...
v5.7.0
String
-
Match a url ending with a string
"end:.jpg"
-
path:...
v7.0.0
String
-
Match a url which has a given path
"path:/posts/2018/7/3"
-
glob:...
v5.7.0
String
-
Match a url using a glob pattern
"glob:http://*.*"
-
express:...
v5.7.0
String
-
Match a url that satisfies an express style path
"express:/user/:user"
-
RegExp
v1.0.0 -
Match a url that satisfies a regular expression
/(article|post)\/\d+/
-
Function
v1.0.0 -
Match if a function returns something truthy. The function will be passed the
url
andoptions
fetch
was called with. Iffetch
was called with aRequest
instance, it will be passedurl
andoptions
inferred from theRequest
instance, with the originalRequest
will be passed as a third argument.This can also be set as a
functionMatcher
in the options parameter, and in this way powerful arbitrary matching criteria can be combined with the ease of the declarative matching rules above.(url, {headers}) => !!headers.Authorization
(_, _, request) => !!request.headers.get('Authorization')
-
Object
v2.0.0 -
The url and function matchers described above can be combined with other criteria for matching a request by passing an an object which may have one or more of the properties described below. All these options can also be define on the third
options
parameters of themock()
method.{url: 'end:/user/profile', headers: {Authorization: 'Basic 123'}}
{query: {search: 'abc'}, method: 'POST'}
Note that if using end:
or an exact url matcher, fetch-mock (for good reason) is unable to distinguish whether URLs without a path end in a trailing slash or not i.e. http://thing
is treated the same as http://thing/
If multiple mocks use the same matcher
but use different options, such as headers
, you will need to use the overwriteRoutes: false
option.
Before v8.3.0 some of the options above had to be passed in as properties on a third parameter of .mock()
response parameter for mock()
String
|
Object
|
Function
|
Promise
|
Response
Configures the http response returned by the mock. Accepts any of the following values or a Promise
for any of them (useful when testing race conditions, loading transitions etc.). Unless otherwise stated, all responses have a 200
status
Argument values
-
Response
v5.0.0 -
A
Response
instance to return unaltered.Note that it must use the same constructor as that used in the
fetch
implementation your application uses. See how to configure thisnew Response('ok', {status: 200})
-
status code
v1.2.0
Integer
-
Return a
Response
with the given status code. The response’sstatusText
will also be set to the default value corresponding to the status200, 404, 503
-
String
v1.0.0 -
Return a 200
Response
with the string as the response bodyServer responded ok
Bad Response
-
config
v1.0.0
Object
-
If an object only contains properties from among those listed below it is used to configure a
Response
to return -
Object
|ArrayBuffer
|...
v1.0.0 -
If the
sendAsJson
option is set totrue
, any object that does not meet the criteria above will be converted to aJSON
string and set as the responsebody
. Otherwise, the object will be set as the responsebody
(useful forArrayBuffer
s etc.) -
Promise
v4.2.0 -
A
Promise
that resolves to any of the options documented abovenew Promise(res => setTimeout(() => res(200), 50))
-
Function
v1.0.0 -
A function that returns any of the options documented above. The function will be passed the
url
andoptions
fetch
was called with. Iffetch
was called with aRequest
instance, it will be passedurl
andoptions
inferred from theRequest
instance, with the originalRequest
will be passed as a third argument.(url, opts) => opts.headers.Authorization ? 200 : 403
(_, _, request) => request.headers.get('Authorization') ? 200 : 403
options parameter for mock() v5.0.0
Object
An object containing further options for configuring mocking behaviour.
In addition to all the options listed below, all the options available for use when using an options object as the first argument to .mock()
can also be passed in on the third argument. These include:
repeat
- defining how many times a mock should match callsheader
,query
,params
,method
,body
- matching calls on criteria other than the url
Response options
-
delay
v7.7.0
Integer
-
Delays responding for the number of milliseconds specified.
-
sticky
v9.7.0
Boolean
-
Avoids a route being removed when
reset()
,restore()
orresetBehavior()
are called. Note - this does not preserve the history of calls to the route -
sendAsJson
v4.1.0
Boolean
[defaulttrue
] -
includeContentLength
v5.13.0
Boolean
[defaulttrue
]
.get(), .post(), .put(), .delete(), .head(), .patch() v5.0.0
Shorthands for mock()
that create routes that only respond to requests using a particular http method.
If you use some other method a lot you can easily define your own shorthands e.g.
fetchMock.purge = function (matcher, response, options) {
return this.mock(
matcher,
response,
Object.assign({}, options, {method: 'PURGE'})
);
}
.once() v5.3.0
Shorthand for mock()
which creates a route that can only mock a single request. (see repeat
option above)
.sticky() v9.7.0
Shorthand for mock()
which creates a route that persists even when restore()
, reset()
or resetbehavior()
are called;
This method is particularly useful for setting up fixtures that must remain in place for all tests, e.g.
fetchMock.sticky(/config-hub.com/, require('./fixtures/start-up-config.json'))
.any(response, options) v9.2.0
Shorthand for mock()
which creates a route that will return a response to any fetch request.
More shorthands
The atomic shorthand methods - .once()
, any()
, and .get()
, .post()
, etc. are combined into a variety of shorthand methods that blend their behaviours.
Methods
-
Any once
v9.2.0
-
Create a route that responds to any single request:
.anyOnce(response, options)
-
Method once
v5.3.0
-
Create a route that only responds to a single request using a particular http method:
.getOnce()
,.postOnce()
,.putOnce()
,.deleteOnce()
,.headOnce()
,.patchOnce()
-
Method any
v9.2.0
-
Create a route that responds to any requests using a particular http method:
.getAny()
,.postAny()
,.putAny()
,.deleteAny()
,.headAny()
,.patchAny()
-
Method any once
v9.2.0
-
Create a route that responds to any single request using a particular http method:
.getAnyOnce()
,.postAnyOnce()
,.putAnyOnce()
,.deleteAnyOnce()
,.headAnyOnce()
,.patchAnyOnce()
.catch(response) v5.0.0
Specifies how to respond to calls to fetch
that don’t match any mocks.
It accepts any valid fetch-mock response, and can also take an arbitrary function to completely customise behaviour. If no argument is passed, then every unmatched call will receive a 200
response
.addMatcher({name, usesBody, matcher}) v9.3.0
Allows adding your own, reusable custom matchers to fetch-mock, for example a matcher for interacting with GraphQL queries, or an isAuthorized
matcher that encapsulates the exact authorization conditions for the API you are mocking, and only requires a true
or false
to be input
Option values
-
name
String
-
The name of your matcher. This will be the name of the property used to hold any input to your matcher.
"*"
-
usesBody
Boolean
-
If your matcher requires access to the body of the request set this to true; because body can, in some cases, only be accessed by fetch-mock asynchronously, you will need to provide this hint in order to make sure the correct code paths are followed.
-
matcher
Function
-
A function which takes a route definition object as input, and returns a function of the signature
(url, options, request) => Boolean
. See the examples below for more detail. The function is passed the fetchMock instance as a second parameter in case you need to access any config.
One intent behind this functionality is to allow companies or publishers of particular toolsets to provide packages that extend fetch-mock to provide a more user friendly experience for developers using fetch to interact with their APIs. The GraphQL use case is a good example of this - the things which a developer might want to match on are buried in the request body, and written in a non-javascript query language. Please get in touch if you’d liek to collaborate on writing such a package.
fetchMock
.addMatcher({
name: 'isAuthorized',
matcher: ({isAuthorized}) => (url, options) => {
const actuallyIsAuthorized = options.headers && options.headers.auth;
return isAuthorized ? actuallyIsAuthorized : !actuallyIsAuthorized;
}
})
.mock({isAuthorized: true}, 200)
.mock({isAuthorized: false}, 401)
fetchMock
.addMatcher({
name: 'graphqlVariables',
matcher: ({graphqlVariables}) => (url, options) => {
if (!/\/graphql$/.test(url)) {
return false;
}
const body = JSON.parse(options.body)
return body.variables && Object.keys(body.variables).length === Object.keys(body.graphqlVariables).length && Object.entries(graphqlVariables).every(([key, val]) => body.variables[key] === val)
}
})
.mock({graphqlVariables: {owner: 'wheresrhys'}}, {data: {account: {
name: 'wheresrhys',
repos: [ ... ]
}}})
// TODO - can't think of a good use case yet
// Raise a PR if you can :-)
.spy(matcher) v5.5.0
Records call history while passing each call on to fetch
to be handled by the network. Optionally pass in a matcher
to scope this to only matched calls, e.g. to fetch a specific resource from the network.
To use .spy()
on a sandboxed fetchMock
, fetchMock.config.fetch
must be set to the same fetch
implementation used in your application. See how to configure this. By default this will be the locally installed version of node-fetch
Setting cookies in the browser
The Set-Cookie
header is used to set cookies in the browser. This behaviour is part of the browser/http spec, not the fetch spec. As fetch-mock prevents requests getting out of js and into the browser, Set-Cookie
will have no effect.
The following code samples demonstrate how to replicate the normal cookie setting behaviour when using fetch-mock.
fetchMock.get("https://mydomain.com", () => {
const cookieString = 'mycookie=hello; Max-Age=3600; Path=/;';
document.cookie = cookieString;
return { status: 200, headers: { 'Set-Cookie': cookieString }};
})
fetchMock.reset();
document.cookie = 'mycookie=; Max-Age=0'
Inspection methods
Inspection fundamentals
Check out the new cheatsheet
fetch-mock
’s inspection methods allow information about how fetch
was called to be retrieved after your application code has run. Most inspection methods take two arguments — filter
and options
— which allow individual, or groups of, fetch
calls to be extracted and examined.
Parameters
-
filter
-
Filter calls to
fetch
using one of the following criteria: -
options
v7.0.0
Object
|String
-
Either an object compatible with the mocking api or a string specifying a http method to filter by. This will be used to filter the list of calls further
The filtering API is powerful, but potentially confusing. If in doubt, add a name
to your route, and pass that name in to retrieve exactly the calls you want.
A note on Regular Expression and Function matchers
To retrieve calls handled by a route with a RegExp
or function
matcher, use a reference to the exact RegExp
|function
you used in your mock, e.g.
const matcherRX = /user\/biff/
fm.mock(matcherRX, 200)
...
fm.called(matcherRX)
not
fm.mock(/user\/biff/, 200)
...
fm.called(/user\/biff/)
The second example will retrieve the expected calls in simple test scenarios because if no routes match using the identifier the RegExp
will be executed as a RegExp
matcher. But in more complex scenarios where e.g. there are several routes handling similar paths, it might retrieve calls that were actually handled by different, similar route e.g.
const matcherRX = /user\/biff/
fm
.mock('end:user/biff')
.mock(matcherRX, 200)
...
// this will retrieve calls handled by either route
fm.called(/user\/biff/)
// this will retrieve only calls handled by the second route
fm.called(matcherRX)
.called(filter, options) v1.0.0
Returns a Boolean indicating whether any calls to fetch
matched the given filter
and options
.calls(filter, options) v1.0.0
Returns an array of all calls to fetch matching the given filter
and options
. Each call is returned as a [url, options]
array. If fetch
was called using a Request
instance, the url
and options
will be inferred from it, and the original Request
will be available as a request
property on this array.
.lastCall(filter, options) v4.0.0
Returns the arguments for the last call to fetch
matching the given filter
and options
. The call is returned as a [url, options]
array. If fetch
was called using a Request
instance, the url
and options
will be inferred from it, and the original Request
will be available as a request
property on this array.
.lastUrl(filter, options) v4.0.0
Returns the url for the last call to fetch
matching the given filter
and options
. If fetch
was last called using a Request
instance, the url will be inferred from this
.lastOptions(filter, options) v4.0.0
Returns the options for the last call to fetch
matching the given filter
and options
. If fetch
was last called using a Request
instance, a set of options
inferred from the Request
will be returned
.lastResponse(filter, options) v9.10.0
Returns the Response
for the last call to fetch
matching the given filter
and options
. This is an experimental feature, very difficult to implement well given fetch’s very private treatment of response bodies.
If .lastResponse()
is called before fetch has been resolved then it will return undefined
When doing all the following:
- using node-fetch
- responding with a real network response (using spy() or fallbackToNetwork)
- using `fetchMock.LastResponse()`
- awaiting the body content
… the response will hang unless your source code also awaits the response body. This is an unavoidable consequence of the nodejs implementation of streams.
To obtain json/text responses await the .json()/.text()
methods of the response
.done(filter) v5.3.0
Returns a Boolean indicating whether fetch
was called the expected number of times (or has been called at least once if repeat
is undefined for the route). It does not take into account whether the fetches
completed successfully.
Parameters
-
matcherOrName
-
Rule for matching calls to
fetch
.
If several routes have the same matcher/url, but use mocking options, the recommended way to handle this is to name each route and filter using those names
Lifecycle methods
.sandbox() v5.6.0
Returns a function that can be used as a drop-in replacement for fetch
. Pass this into your mocking library of choice. The function returned by sandbox()
has all the methods of fetch-mock
exposed on it and maintains its own state independent of other instances, so tests can be run in parallel.
fetchMock
.sandbox()
.mock('http://domain.com', 200)
.flush(waitForBody) v5.11.0
Returns a Promise
that resolves once all fetches handled by fetch-mock have resolved
Useful for testing code that uses fetch
but doesn’t return a promise.
If waitForBody
is true
, the promise will wait for all body parsing methods (res.json()
, res.text()
, etc.) to resolve too.
.restore(), .reset() v7.0.0
Resets fetch()
to its unstubbed state and clears all data recorded for its calls. restore()
is an alias for reset()
. Optionally pass in a {sticky: true}
option to remove even sticky routes.
Both methods are bound to fetchMock, and can be used directly as callbacks e.g. afterEach(fetchMock.reset)
will work just fine. There is no need for afterEach(() => fetchMock.reset())
.resetHistory() v7.0.0
Clears all data recorded for fetch
’s calls. It will not restore fetch to its default implementation
resetHistory()
is bound to fetchMock, and can be used directly as a callback e.g. afterEach(fetchMock.resetHistory)
will work just fine. There is no need for afterEach(() => fetchMock.resetHistory())
.resetBehavior() v7.0.0
Removes all mock routes from the instance of fetch-mock
, and restores fetch
to its original implementation if mocking globally. Will not clear data recorded for fetch
’s calls. Optionally pass in a {sticky: true}
option to remove even sticky routes.
Troubleshooting
General
The first step when debugging tests should be to run with the environment variable DEBUG=fetch-mock*
. This will output additional logs for debugging purposes.
fetch
is assigned to a local variable, not a global
First of all, consider whether you could just use fetch
as a global. Here are 3 reasons why this is a good idea:
- The
fetch
standard defines it as a global (and in some cases it won’t work unless bound towindow
), so to write isomorphic code it’s probably best to stick to this pattern isomorphic-fetch
takes care of installing it as a global in Node.js or the browser, so there’s no effort on your part to do so.fetch-mock
is primarily designed to work withfetch
as a global and your experience of using it will be far more straightforward if you follow this pattern
Still not convinced?
In that case fetchMock.sandbox()
can be used to generate a function which you can pass in to a mock loading library such as mockery
instead of fetch
fetch
doesn’t seem to be getting mocked?
- If using a mock loading library such as
mockery
, are you requiring the module you’re testing after registeringfetch-mock
with the mock loader? You probably should be (Example incorrect usage). If you’re using ES6import
it may not be possible to do this without reverting to usingrequire()
sometimes. - If using
isomorphic-fetch
in your source, are you assigning it to afetch
variable? You shouldn’t be i.e.import 'isomorphic-fetch'
, notimport fetch from 'isomorphic-fetch'
require('isomorphic-fetch')
, notconst fetch = require('isomorphic-fetch')
Environment doesn’t support requiring fetch-mock?
- If your client-side code or tests do not use a loader that respects the browser field of package.json use
require('fetch-mock/es5/client')
. - If you need to use fetch-mock without commonjs, you can include the precompiled
node_modules/fetch-mock/es5/client-browserified.js
in a script tag. This loads fetch-mock into thefetchMock
global variable. - For server side tests running in Node.js 0.12 or lower use
require('fetch-mock/es5/server')
Matching Request
objects in node fails
In node, if your Request
object is not an instance of the Request
constructor used by fetch-mock, you need to set a reference to your custom
request class. This needs to be done if you are mocking the Request
object
for a test or you are running npm with a version below 3.
- use
fetchMock.config.Request = myRequest
, wheremyRequest
is a reference to the Request constructor used in your application code.