How to unit test API calls with mocked fetch() in react-native with Jest

Unit TestingReact NativeJestjs

Unit Testing Problem Overview


In React Native I use fetch to perform network requests, however fetch is not an explicitly required module, so it is seemingly impossible to mock in Jest.

Even trying to call a method which uses fetch in a test will result in:

> ReferenceError: fetch is not defined

Is there a way to test such API requests in react native with Jest?

Unit Testing Solutions


Solution 1 - Unit Testing

Inside your test case you can mock any function you want by using Jest's mocks:

fetch = jest.fn(() => Promise.resolve());

This approach works only for the promise-based test cases (see pit in the Jest docs).

As far as fetch is an async function, you need to run all your tests using pit (read more about async tests here).

Solution 2 - Unit Testing

Another approach where you mock the global fetch object:

const mockSuccesfulResponse = (
  status = 200,
  method = RequestType.GET,
  returnBody?: object
) => {
  global.fetch = jest.fn().mockImplementationOnce(() => {
    return new Promise((resolve, reject) => {
      resolve({
        ok: true,
        status,
        json: () => {
          return returnBody ? returnBody : {};
        },
      });
    });
  });
};

The above helper method can be modified any way you want :-) Hope it helps someone

Solution 3 - Unit Testing

Rather than rolling your own mock, you can use the jest-fetch-mock npm package to override the global fetch object. That package allows you to set up fake responses and verify sent requests. See that link for extensive usage examples.

Solution 4 - Unit Testing

I solved this by adding isomorphic-fetch.

$ npm install --save isomorphic-fetch

and using it like

import fetch from 'isomorphic-fetch';
...
fetch('http://foo.com');

whatwg-fetch might work as well

Solution 5 - Unit Testing

Suppose you want to test resolve and reject cases, for this first you mock the fetch behaviour and then use Jest's rejects and resolves methods with with assertion block


function fetchTodos() {
  return fetch(`${window.location.origin}/todos.json`)
    .then(response => response.json())
    .catch(error => console.log(error))
}
describe('fetchTodos', () => {
  it('returns promise resolving to parsed response', () => {
    global.fetch = jest.fn(() => Promise.resolve({ json: () => ''}))
    expect(fetchTodos()).resolves.toBe('');
  })
  it('returns promise handling the error', async () => {
    global.fetch = jest.fn(() => Promise.reject(''))
    expect(fetchTodos()).rejects.toBe('')
  })
})

Solution 6 - Unit Testing

As @ArthurDenture recommended, you can use fetch-mock, but there are some additional packages you will need to install to make it work with React Native and Jest:

$ npm install --save-dev fetch-mock
$ npm install --save-dev babel-plugin-transform-runtime
$ npm install --save-dev babel-preset-env

You can then mock fetch requests in your tests. Here is an example:

// __tests__/App.test.js
import React from 'react';
import App from '../App';
import fetchMock from 'fetch-mock';
import renderer from 'react-test-renderer';

it('renders without crashing', () => {
  fetchMock.mock('*', 'Hello World!');
  const rendered = renderer.create(<App />).toJSON();
  expect(rendered).toBeTruthy();
});

Solution 7 - Unit Testing

Due to problems using fetch-mock with jest, I've release fetch-mock-jest. It basically gives the full fetch-mock api, but with a few jest-specific helpers, and works out of the box with jest, without needing to do any tricky wiring yourself

Solution 8 - Unit Testing

As shown in the react-testing-library documentation, you can use the jest.spyOn() function, which will mock the fetch function only for the next time it is called.

const fakeUserResponse = {token: 'fake_user_token'}
jest.spyOn(window, 'fetch').mockImplementationOnce(() => {
  return Promise.resolve({
    json: () => Promise.resolve(fakeUserResponse),
  })
})

react-testing-library

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJ TView Question on Stackoverflow
Solution 1 - Unit TestingAlexey KureevView Answer on Stackoverflow
Solution 2 - Unit TestingjhmView Answer on Stackoverflow
Solution 3 - Unit TestingArthurDentureView Answer on Stackoverflow
Solution 4 - Unit TestingHarry MorenoView Answer on Stackoverflow
Solution 5 - Unit TestingPurkhalo AlexView Answer on Stackoverflow
Solution 6 - Unit TestingTom ArandaView Answer on Stackoverflow
Solution 7 - Unit TestingwheresrhysView Answer on Stackoverflow
Solution 8 - Unit TestingSteven KaufmanView Answer on Stackoverflow