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), where matcher is an exact url or regex to match, and response is a status code, string or object literal.
  • You can also use fetchMock.once() to limit to a single call or fetchMock.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 leave matcher out if you just want to check fetch was called at all).
  • fetchMock.lastCall(), fetchMock.lastUrl() or fetchMock.lastOptions() give you access to the parameters last passed in to fetch.
  • fetchMock.done() will tell you if fetch was called the expected number of times.

Tearing down your mock

  • fetchMock.resetHistory() resets the call history.
  • fetchMock.reset() or fetchMock.restore() will also restore fetch() 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 of fetch-mock.
    • A browser that supports the fetch API either natively or via a polyfill/ponyfill

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 to global 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 and server.js are the entry points. The directory also contains a package.json file specifying that the directory contains commonjs modules.
  • /esm directory - This contains builds of fetch-mock, exported as ES modules. client.js and server.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 and server.js, both of which are commonjs modules
    • client-legacy.js, which is the same as client.js, but includes some babel polyfill bootstrapping to ease running it in older environments
    • client-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 of package.json use require('fetch-mock/es5/client') or import 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 the fetchMock 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 [default true]

Always convert objects passed to .mock() to JSON strings before building reponses. Can be useful to set to false globally if e.g. dealing with a lot of ArrayBuffers. When true the Content-Type: application/json header will also be set on each response.

includeContentLength v5.13.0
Boolean [default true]

Sets a Content-Length header on each response.

fallbackToNetwork v6.5.0
Boolean | String [default false]
  • true: Unhandled calls fall through to the network
  • false: Unhandled calls throw an error
  • 'always': All calls fall through to the network, effectively disabling fetch-mock.
overwriteRoutes v6.0.0
Boolean [default undefined]

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 thrown
  • true: Overwrites the existing route
  • false: 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 [default true]

Print a warning if any call is caught by a fallback handler (set using catch(), spy() or the fallbackToNetwork 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 custom fetch implementation, if your application uses one

Request v5.9.0
Constructor

The Request constructor of a custom fetch implementation, if your application uses one

Response v5.0.0
Constructor

The Response constructor of a custom fetch 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:

  1. 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.

  2. 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.

  3. 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.

  4. 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 and options fetch was called with. If fetch was called with a Request instance, it will be passed url and options inferred from the Request instance, with the original Request 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 the mock() method.

{url: 'end:/user/profile', headers: {Authorization: 'Basic 123'}}
{query: {search: 'abc'}, method: 'POST'}
url v8.3.0
String | RegExp

Use any of the String or RegExp matchers described above. Note that the property name ‘matcher’ can be used instead of ‘url’, but this is deprecated and support will be dropped in the next major version, so prefer to use ‘url’

functionMatcher v7.3.0
Function

Use a function matcher, as described above

method v2.1.0
String

Match only requests using this http method. Not case-sensitive

get, POST
headers v1.0.0
Object | Headers

Match only requests that have these headers set

{"Accepts": "text/html"}
body v7.4.0
Object

Match only requests that send a JSON body with the exact structure and properties as the one provided here.

Note that if matching on body and using Request instances in your source code, this forces fetch-mock into an asynchronous flow before it is able to route requests effectively. This means no inspection methods can be used synchronously. You must first either await the fetches to resolve, or await fetchMock.flush(). The popular library Ky uses Request instances internally, and so also triggers this mode.

{ "key1": "value1", "key2": "value2" }
matchPartialBody v9.1.0
Boolean

Match calls that only partially match a specified body json. See global configuration for details.

query v6.0.0
Object

Match only requests that have these query parameters set (in any order). Query parameters are matched by using Node.js querystring module. In summary the bahaviour is as follows

  • strings, numbers and booleans are coerced to strings
  • arrays of values are coerced to repetitions of the key
  • all other values, including undefined, are coerced to an empty string The request will be matched whichever order keys appear in the query string. Any query parameters sent in the request which are not included in the keys of the object provided will be ignored.
{"q": "cute+kittenz"} // matches '?q=cute kittenz' or ?q=cute+kittenz' or ?q=cute+kittenz&mode=big'
{"tags": ["cute", "kittenz"]} // matches `?q=cute&q=kittenz`
{"q": undefined, inform: true} // matches `?q=&inform=true`
params v6.0.0
Object

When the express: keyword is used in a string matcher, match only requests with these express parameters

{"section": "feed", "user": "geoff"}
repeat v6.0.0
Integer

Limits the number of times the route can be used. If the route has already been called repeat times, the call to fetch() will fall through to be handled by any other routes defined (which may eventually result in an error if nothing matches it)

name v1.0.0
String

A unique string naming the route. Used to subsequently retrieve references to the calls handled by it. Only needed for advanced use cases.

overwriteRoutes v6.0.0
Boolean

See global configuration

response v2.0.0

Instead of defining the response as the second argument of mock(), it can be passed as a property on the first argument. See the response documentation for valid values.

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 this

new Response('ok', {status: 200})
status code v1.2.0
Integer

Return a Response with the given status code. The response’s statusText will also be set to the default value corresponding to the status

200, 404, 503
String v1.0.0

Return a 200 Response with the string as the response body

Server 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

body v1.0.0
String | Object

Set the Response body. See the non-config Object section of the docs below for behaviour when passed an Object

Server responded ok
{ token: 'abcdef' }
status v1.0.0
Integer

Set the Response status

200, 404, 503
headers v1.0.0
Object

Set the Response headers

{'Content-Type': 'text/html'}
redirectUrl v6.0.0
String

The url from which the Response should claim to originate from (to imitate followed directs). Will also set redirected: true on the response

throws v1.0.0
Error

Force fetch to return a Promise rejected with the value of throws

new TypeError('Failed to fetch')
Object | ArrayBuffer | ... v1.0.0

If the sendAsJson option is set to true, any object that does not meet the criteria above will be converted to a JSON string and set as the response body. Otherwise, the object will be set as the response body (useful for ArrayBuffers etc.)

Promise v4.2.0

A Promise that resolves to any of the options documented above

new 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 and options fetch was called with. If fetch was called with a Request instance, it will be passed url and options inferred from the Request instance, with the original Request 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 calls
  • header, 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() or resetBehavior() are called. Note - this does not preserve the history of calls to the route

sendAsJson v4.1.0
Boolean [default true]

See global configuration

includeContentLength v5.13.0
Boolean [default true]

See global configuration

.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:

undefined v6.0.0

Retrieve all calls made to fetch

true v6.0.0

Retrieve all calls to fetch matched by some route defined by fetch-mock. The string 'matched' can be used instead of true to make tests more readable

const {MATCHED, fetchMock} = require('fetch-mock');
...
fetchMock.calls(MATCHED)
false v6.0.0

Retrieve all calls to fetch not matched by some route defined by fetch-mock. The string 'unmatched' can be used instead of false to make tests more readable

const {UNMATCHED, fetchMock} = require('fetch-mock');
...
fetchMock.calls(UNMATCHED)
"matched" | "unmatched" v9.0.0

Aliases for true and false

routeIdentifier v2.0.0
String | RegExp | function

All routes have an identifier:

  • If it’s a named route, the identifier is the route’s name
  • If the route is unnamed, the identifier is the value of the matcher argument that was passed in to .mock()

All calls that were handled by the route with the given identifier will be retrieved

matcher v7.0.0
String | RegExp | function

Any matcher compatible with the mocking api can be passed in to filter the calls arbitrarily. The matcher will be executed using exactly the same rules as the mocking api

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.

undefined | true

Returns true if all routes have been called the expected number of times

routeIdentifier
String|RegExp|function

All routes have an identifier:

  • If it’s a named route, the identifier is the route’s name
  • If the route is unnamed, the identifier is the matcher passed in to .mock()

Returns true if the routes specified by the identifier has been called the expected number of times

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.

resetBehavior() is bound to fetchMock, and can be used directly as a callback e.g. afterEach(fetchMock.resetBehavior) will work just fine. There is no need for afterEach(() => fetchMock.resetBehavior())

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 to window), 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 with fetch 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 registering fetch-mock with the mock loader? You probably should be (Example incorrect usage). If you’re using ES6 import it may not be possible to do this without reverting to using require() sometimes.
  • If using isomorphic-fetch in your source, are you assigning it to a fetch variable? You shouldn’t be i.e.
    • import 'isomorphic-fetch', not import fetch from 'isomorphic-fetch'
    • require('isomorphic-fetch'), not const 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 the fetchMock 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, where myRequest is a reference to the Request constructor used in your application code.