wheresrhys / fetch-mock-jest

Jest wrapper for fetch-mock, a comprehensive stub for fetch
http://www.wheresrhys.co.uk/fetch-mock/
MIT License
60 stars 11 forks source link

No fallback response defined for GET to /foo #45

Closed hacknlove closed 1 month ago

hacknlove commented 3 years ago

What am I missing here?

const fetch = require("node-fetch");
jest.mock("node-fetch", () => require("fetch-mock-jest").sandbox());
const fetchMock = require("fetch-mock-jest");

describe("bug", () => {
  it("should work!", async () => {
    fetchMock.get("/foo", { bar: "buz" });

    const response = await fetch("/foo").to((r) => r.json());

    expect(response).toEqual({ bar: "buz" });
  });
});
dsandbox@sse-sandbox-twf31:/sandbox$ yarn test
yarn run v1.22.10
warning package.json: No license field
$ jest
 FAIL  src/bug.test.js
  bug
    ✕ should work! (19 ms)

  ● bug › should work!

    fetch-mock: No fallback response defined for GET to /foo

       7 |     fetchMock.get("/foo", { bar: "buz" });
       8 |
    >  9 |     const response = await fetch("/foo").to((r) => r.json());
         |                            ^
      10 |
      11 |     expect(response).toEqual({ bar: "buz" });
      12 |   });

      at Function.Object.<anonymous>.FetchMock.executeRouter (node_modules/fetch-mock/cjs/lib/fetch-handler.js:230:9)
      at Function.Object.<anonymous>.FetchMock._fetchHandler (node_modules/fetch-mock/cjs/lib/fetch-handler.js:144:34)
      at Function.Object.<anonymous>.FetchMock.fetchHandler (node_modules/fetch-mock/cjs/lib/fetch-handler.js:135:14)
      at Function.jestifiedInstance.fetchHandler (node_modules/fetch-mock-jest/jestify.js:27:18)
      at fetch (node_modules/fetch-mock/cjs/lib/index.js:52:51)
      at Object.<anonymous> (src/bug.test.js:9:28)

  console.warn
    Unmatched GET to /foo

       7 |     fetchMock.get("/foo", { bar: "buz" });
       8 |
    >  9 |     const response = await fetch("/foo").to((r) => r.json());
         |                            ^
      10 |
      11 |     expect(response).toEqual({ bar: "buz" });
      12 |   });

      at Function.Object.<anonymous>.FetchMock.executeRouter (node_modules/fetch-mock/cjs/lib/fetch-handler.js:221:11)
      at Function.Object.<anonymous>.FetchMock._fetchHandler (node_modules/fetch-mock/cjs/lib/fetch-handler.js:144:34)
      at Function.Object.<anonymous>.FetchMock.fetchHandler (node_modules/fetch-mock/cjs/lib/fetch-handler.js:135:14)
      at Function.jestifiedInstance.fetchHandler (node_modules/fetch-mock-jest/jestify.js:27:18)
      at fetch (node_modules/fetch-mock/cjs/lib/index.js:52:51)
      at Object.<anonymous> (src/bug.test.js:9:28)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        1.827 s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
sandbox@sse-sandbox-twf31:/sandbox$ ^C

https://codesandbox.io/s/bitter-violet-twf31?file=/src/bug.test.js:0-374

julienw commented 9 months ago

I hope you found your solution, but I believe the problem is that your fetchMock isn't the sandbox from your node-fetch mock.

Indeed:

// By the magic of babel-jest, this `fetch` is actually a sandbox of the mock
// as defined in the next line.
const fetch = require("node-fetch");

// This mocks "node-fetch" to return a new sandbox for each new require.
// By the magic of babel-jest this runs first thing in this file.
// I also believe that the return value is cached by node, so if several files all do
// `require("node-fetch")` they'll all get the same sandbox -- this is required for all
// this to work.
jest.mock("node-fetch", () => require("fetch-mock-jest").sandbox());

// But _here_ you require from "fetch-mock-jest", _not_ from "node-fetch"
// So you don't get the same object! Instead of getting the mock to "node-fetch",
// you get the mock to the global fetch.
const fetchMock = require("fetch-mock-jest");

describe("bug", () => {
  it("should work!", async () => {
    // You configure the global mock.
    fetchMock.get("/foo", { bar: "buz" });

    // but you use the mock to "node-fetch" here.
    // So this doesn't work as you expect.
    const response = await fetch("/foo").to((r) => r.json());

    expect(response).toEqual({ bar: "buz" });
  });

The fix is easy: remove the fetchMock object, and use directly fetch when you configure it:

const fetch = require("node-fetch");
jest.mock("node-fetch", () => require("fetch-mock-jest").sandbox());

describe("bug", () => {
  it("should work!", async () => {
    fetch.get("/foo", { bar: "buz" });

    const response = await fetch("/foo").then((r) => r.json());

    expect(response).toEqual({ bar: "buz" });
  });
});

(please note that I also changed an error in the fetch call => you used the function to which doesn't exist, I replaced it with then.)