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

Viewed 54013

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?

8 Answers

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

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('')
  })
})

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();
});

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

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

Related