avenmia
avenmia

Reputation: 2605

'body used already for' error when mocking node fetch?

I'm trying to mock node-fetch with jest for my azure functions. In the test I have the following:

index.test.ts

jest.mock("node-fetch");
import fetch from "node-fetch";
const {Response} = jest.requireActual("node-fetch");

// Setup code here...

const expectedResult: User = {
        user_id: "1",
        email: "[email protected]",
        name: "testUser",
        nickname: "test",
        picture: "pic",
        app_metadata: {
            email: "[email protected]"
        }
    };
    (fetch as jest.MockedFunction<typeof fetch>).mockReturnValue(new Response(JSON.stringify(expectedResult)));

When I call it I'm doing the following:

index.ts


const options = {
                method: 'PATCH',
                headers: { "Content-Type": 'application/json', authorization: `Bearer ${accessToken}`},
                body: body
            };

const userResponse = await fetch(usersEndpoint, options);
const jsonResult = await userResponse.json();
context.res = {
                body: jsonResult
            };

When it hits the "await userResponse.json()" I get "body used already for" error. I have another test that is set up in a similar manner which works so I'm not sure why it's saying the body is used up from the await fetch call. Any help would be appreciated.

Upvotes: 9

Views: 20253

Answers (2)

Estus Flask
Estus Flask

Reputation: 222493

Response object is supposed to be used once per request while mocked fetch returns the same object for multiple requests. Also, it should return a promise of a response, not a response itself.

A correct way to mock it is:

fetch.mockImplementation(() => Promise.resolve(
  new Response(JSON.stringify(expectedResult))
));

It's unnecessary to use Response and follow the restrictions it imposes, especially since there's no native Response in Node.

It can be:

fetch.mockResolvedValue({
  json: jest.fn(() => expectedResult)
});

Upvotes: 6

avenmia
avenmia

Reputation: 2605

My problem was I had a call to another function that used fetch which was resolving my mock implementation. Once I mocked that return value:

 (fetch as jest.MockedFunction<typeof fetch>).mockReturnValue(new Response(JSON.stringify(expectedResult)));

ended up working.

@Estus Flask's answer also ended up working.

Upvotes: 0

Related Questions