Photo by João Silas on Unsplash

Mocking and testing fetch with Jest

Rishabh
2 min readJun 4, 2018

Here’s a quick note about mocking and testing fetch calls with Jest.

Let’s take an example React component, ExampleComponent:

Let’s write a test for it using Jest and Enzyme, ExampleComponent.test.js:

Some points to note here are:

  1. By passing the done function here, we’re telling Jest to wait until the done callback is called before finishing the test. See Testing Asynchronous Code docs for more details.
  2. Since we await the call to response.json() in ExampleComponent.js, we Promise.resolve it in the test to a mockSuccessResponse object.
  3. Since we are awaiting the call to fetch('https://url-of-your-server.com/example/json'), in ExampleComponent.js, and expecting the returned object to contain a json function, which returns another Promise, we Promise.resolve to an object containing such a json function.
  4. We spy on window.fetch and mock it’s implementation to return the Promise object described in 3. See the section below if you are getting an error like, “Cannot spy the fetch property because it is not a function; undefined given instead”.
  5. We invoke Enzyme to shallow render, which also invokes the React lifecycle methods *.
  6. Wrapping our assertion code inside a process.nextTick() ensures that the functions queued in the current event loop are completed, thus also ensuring that our Promises and other code inside ExampleComponent is done executing.
  7. Optionally, we clear the mock.
  8. We invoke done to tell Jest that this test case is complete.

Note that this was a minimal example for demonstration & education purposes only. There are a lot of things I would do differently if I were writing production-ready code (e.g. abstracting away the data fetching logic, using static typing etc.).

“Cannot spy the fetch property because it is not a function; undefined given instead”

If you get an error, “Cannot spy the fetch property because it is not a function; undefined given instead”, that’s because fetch has not been polyfill’d in your Jest’s JSDOM environment. As of this writing, there is an open request (jsdom/jsdom#1724) to add fetch API headers into JSDOM.

So as a workaround, instead of using jest.spyOn, you can…

global.fetch = jest.fn().mockImplementation(() => mockFetchPromise);

… and clean it up later using…

global.fetch.mockClear();
delete global.fetch;

* Note about React lifecycle methods and Enzyme v3:

As of Enzyme v3, the shallow API does call React lifecycle methods such as componentDidMount and componentDidUpdate.

--

--

Rishabh

Software engineer specializing in accessibility. A11y advocate. ♥️s design, astrophysics, art, travel, photography & writing.