msw: ReferenceError: fetch is not defined

Environment

| msw | 0.28.1 |

Request handlers

I’m currently using msw to mock fetch in my jest test. The component uses the default javascript fetch and works fine with that.

When I run the test without adding node-fetch to my component, the test fails : ReferenceError: fetch is not defined When I run the test with “const fetch = require(“node-fetch”);” in my component file, the test works fine (but the component breaks when it’s rendered in a browser so it can’t be a solution for me)

Also, I noticed that if I don’t use node-fetch but I install jest-fetch-mock and I disable it (to still use MSW), then things work require('jest-fetch-mock').enableMocks() fetchMock.dontMock()

Without node-fetch or jest-fetch-mock it says fetch is not defined (but the component works fine with the javascript fetch)

I’m so confused, installing but not using jest-fetch-mock make the error go away and why do I need all this, why can’t I mock the window.fetch with msw ?

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 4
  • Comments: 22 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Hey, @pqr. I’m sorry to hear you’re having trouble setting up your tests.

You don’t find fetch mentions in our docs because this isn’t the library’s responsibility. You need to polyfill fetch yourself. The problem is that you rarely realize you do, as some tools (like Create React App) do that for you, making you think fetch is automagically available in tests.

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 know our examples don’t mention this test setup either, but you need to forgive us on this: we write examples that use common tech (such as CRA) and are easy to get started with.

I’ve added a new usage example that will help you set up Jest and MSW:

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 may use window.fetch. How this works usually is testing environment polyfills fetch for you (i.e. with node-fetch, whatwg-fetch, or any other compatible polyfills). Most of the frameworks like CRA come with that polyfill built-in, so you rarely pay attention that you need it.

The solution to your issue is to include a suitable fetch polyfill in your testing setup (just as @msutkowski has pointed out).

The other part is this question:

I’m so confused, installing but not using jest-fetch-mock make the error go away and why do I need all this, why can’t I mock the window.fetch with msw ?

It’d be much more straightforward to understand and debug any potential MSW issues when you realize it’s request client-agnostic. MSW doesn’t have any fetch-related logic and doesn’t rely on fetch in any way. Seeing errors like “fetch is not defined” may hint to you that it’s not a library’s problem.

It’s the core philosophy and one of the main benefits of MSW: you forget about mocking fetch/axios/etc. Departing from that mentally is also helpful to keep your tests clean and debugging easier.

@VadimZP thank you!

Adding only globals: { fetch } to jest config worked here!

Hey @onimougwo,

This is a configuration issue. You need to include a fetch polyfill (like node-fetch as you mention) in your setupTests file and not in the component. You should just be able to require('node-fetch') or import it, whichever syntax you’re using, and things will just work.

@kettanaito thank you so much for your example with whatwg-fetch. This approached fixed my problem with ReferenceError: fetch is not defined too.

But before I tried to use node-fetch like this and it didn’t do the trick:

import nextJest from "next/jest.js";
import 'whatwg-fetch'

const createJestConfig = nextJest({
  // Provide the path to your Next.js app to load next.config.js and .env files in your test environment
  dir: "./",
});

// Add any custom config to be passed to Jest
/** @type {import('jest').Config} */
const config = {
  // Add more setup options before each test is run
  // setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  setupFilesAfterEnv: ["./jest.setup.ts"],
  testEnvironment: "jest-environment-jsdom",
  globals: {
    fetch,
  },
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
export default createJestConfig(config);

Hey, @MikeYermolayev.

Take a look at this Jest + MSW example that uses the most minimal Jest setup there can be. It uses whatwg-fetch as the fetch polyfill. Take a look at how it’s written, compare it with your test configuration. Let us know if you need any assistance, we’d be happy to help given a reproduction repository.

@Nargonath, unfortunately, when using Jest, people still have to explicitly map fetch and other Fetch API classes manually in the globals option in jest.config.js. That’s just how Jest works.

By the way for people still coming here, starting from node@18 fetch is baked into node so you don’t need a polyfill anymore, see: https://developer.mozilla.org/en-US/docs/Web/API/fetch#browser_compatibility.

My problem was that it was working locally on my machine (running node@18.17.0) but it didn’t work in the CI. I figured node was shipped with the open-jdk image which had node@16 hence fetch was not defined. Upgrading the image to one with node@18 fixed the fetch is not defined error for me.

Hi, @abdofola. No, MSW never stated to mock any request-issuing clients. In fact, not doing so is one of the things that sets MSW apart from the alternatives. But even with those, you must ensure your test environment can run your code, which often means polyfilling fetch or other modules your code depends on.

Thank you so much @kettanaito

@kettanaito now I catch the idea! Thank you for complete example without CRA, it has really helped me to figure out the point of fetch polyfill now.

Hey @onimougwo,

This is a configuration issue. You need to include a fetch polyfill (like node-fetch as you mention) in your setupTests file and not in the component. You should just be able to require('node-fetch') or import it, whichever syntax you’re using, and things will just work.

I’ve tried to import node-fetch in setupTests, but my React component still throws an error “ReferenceError: fetch is not defined” when I run tests under node environment.

Not clear how to define fake fetch function globally?

I red all MSW documentation and all examples in repository and did not manage to find example how to test React components (which uses fetch internally) with Jest and MSW .

For example, let’s look on this part of documentation “Getting Started -> Integrate -> Node” - https://mswjs.io/docs/getting-started/integrate/node - fetch not mentioned there. I thought that MSW provides some fake fetch automatically, looks like it’s not the case. I’m stumped.

I red brilliant article https://kentcdodds.com/blog/stop-mocking-fetch with headline “Stop mocking fetch” and irony is that after I did step by step all code examples in this article I got “ReferenceError: fetch is not defined” - so to stop mocking fetch I do need to mock fetch? I’am completely lost.

Do you have any open-source example how to test React components (which uses fetch internally) with Jest and MSW?