16

I have the following Jest test code to test a fetch to an endpoint:

import MovieApiService from 'services/MovieApiService';
import movies from '../constants/movies';

describe('MovieApiService', () => {

  test('if jest work correctly', () => {
    expect(true).toBe(true);
  });

  test('get an array of popular movies', () => {
    global.fetch = jest.mock('../mocks/movies');
    const movieApiService = new MovieApiService();
    return movieApiService.getPopularMovies()
      .then(data => expect(data).toBe(movies));
  });
});

But I am getting:

Enter image description here

I know that the movieApiService.getPopularMovies() is a JavaScript fetch request, but Node.js does not have the fetch API, so how I can I make this test to work using Jest?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jean
  • 5,201
  • 11
  • 51
  • 87
  • 1
    @ÉtienneMiret this question is 5 years old – Jean Jun 08 '23 at 11:34
  • Here is a similar case https://stackoverflow.com/questions/58785617/cors-error-error-cross-origin-http-localhost-forbidden-in-reactjs-jest-te/76718461. See my answer using `supertest` library – Michael Rovinsky Jul 19 '23 at 06:24

5 Answers5

10

I can't test this with the code you supply, but installing and importing the npm module jest-fetch-mock should do the trick.

ajrussellaudio
  • 374
  • 3
  • 12
8

Try to keep you mock implementation specific to test cases and if multiple test cases are bound to use the same implementation then wrap them up in a describe block along with a beforeEach call inside it.

This helps in describing mock implementation specific to the scenario being tested.

It is hard to test your implementation with the code you supplied, but let's try switching your mock implementation to something like this:

// This is just dummy data - change its shape in a format that your API renders.
const dummyMoviesData = [
    {title: 'some-tilte-1', body: 'some-1'},
    {title: 'some-tilte-2', body: 'some-2'},
    {title: 'some-tilte-3', body: 'some-3'}
];
global.fetch = jest.fn(() => Promise.resolve(dummyMoviesData));

Now, whenever you movie service API gets called, you may expect the outcome to be of shape of dummyMoviesData and even match it.

So,

expect(outcome).toMatchObject(dummyMoviesData);

or

expect(outcome).toEqual(dummyMoviesData);

should do the trick.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Himanshu Singh
  • 970
  • 2
  • 6
  • 18
  • This technically works but is incorrect as the result of fetch should not be directly the data but a promise of a Reponse with a `ok` flag, holding a api providing `json()`and `text()` methods, etc. All of this implies additional work that is implicitly handled by solutions like `jest-fetch-mock`. – Jérôme Beau Oct 14 '21 at 08:46
8

As of October 2020, an approach to resolve the error TypeError: fetch is not function is to include the polyfill for fetch using whatwg-fetch.

The package provides a polyfill for .fetch and is well supported and managed by Github.com employees since 2016. It is advisable to read the caveats to understand if whatwg-fetch is the appropriate solution.

Usage is simple for Babel and es2015+, just add to your file.

import 'whatwg-fetch'

If you are using with Webpack add the package in the entry configuration option before your application entry point.

entry: ['whatwg-fetch', ...]

You can read the comprehensive documentation at https://github.github.io/fetch/

If you are unfamiliar with WhatWG, learn more about the Web Hypertext Application Technology Working Group on their website.

Ben Smith
  • 19,589
  • 6
  • 65
  • 93
gtzilla
  • 1,265
  • 1
  • 16
  • 21
6

Installing and adding the below snippet to the top of my jest file fixed it for me:

import "isomorphic-fetch"

Dharman
  • 30,962
  • 25
  • 85
  • 135
rishikarri
  • 3,462
  • 2
  • 13
  • 13
0

The first thing to understand is that fetch is a browser-specific API and doesn't exist in Node.js. Jest tests run in Node.js, although they execute your components that uses window.fetch.

In reality, your React component gets rendered in Node.js when you run Jest, and fetch doesn't exist in Node.js—that's the whole reason to polyfill it.

I knew you knew this but I wrote them for other who don't know why this happened.

To solve this problem follow the steps below: 1: install "whatwg-fetch" package (npm i whatwg-fetch). 2: In the root of your project make a 'jest.config.js' file and put the codes below:

module.exports = {
    setupFilesAfterEnv: ['./jest.setup.js'],
}

3: Make a 'jest.setup.js' file and put the code below into it:

import 'whatwg-fetch'

Now your 'fetch' requests in a jest test must work. You can check the link below for more information:

https://github.com/mswjs/examples/tree/master/examples/with-jest