Search code examples
typescriptfetch-apihttpresponsets-jestjest-fetch-mock

Mocking fetch return response using Jest in Typescript


I have a function that calls fetch() and handles different cases of its response data. When trying to mock the global fetch function using Jest I am having trouble with the Response type. I only need the response.ok, and response.json properties. How can I set the return data of fetch without having to write out all of the required properties?

My code:

describe('steam data fetch function', () => {
    const fetchMock = jest.spyOn(global, 'fetch').mockImplementation(
        jest.fn(() =>
            Promise.resolve({
                ok: false,
                json: () => Promise.resolve({ data: 'empty' }),
            })
        ) as jest.Mock
    );

    // Begin tests
    test('handles invalid data correctly', () => {
        fetchMock.mockResolvedValueOnce({
            ok: false,
            json: () => Promise.resolve({ data: 'test1' }),
        }) as jest.Mock;

        // expect function using fetch to...
    });
    // more tests
    // each test sets new fetchMock.mockResolvedValueOnce
});

In my fetchMock.mockResolvedValueOnce statement I am currently getting tsError: Argument of type '{ ok: false; json: () => Promise<{ data: string; }>; }' is not assignable to parameter of type 'Response | Promise<Response>'. Type '{ ok: false; json: () => Promise<{ data: string; }>; }' is missing the following properties from type 'Response': headers, redirected, status, statusText, and 9 more.ts(2345)

I tried adding one of the missing properties which reduces the missing ones by 1, but I want to avoid having to write all of the properties out.

Solution: New working version from comments:

test('handles invalid data correctly', () => {
        fetchMock.mockResolvedValueOnce({
            ok: false,
            json: () => Promise.resolve({ data: 'test1' }),
        } as unknown as Response);

        // expect function using fetch to...
    });

After very quickly looking into the Response on MDN it seems I could do this a lot more thoroughly, but in this case this solution is enough.


Solution

  • Cast first to unknown and then to the type you want, Response.

    So you'd write Promise.resolve({ data: 'empty' } as unknown as Response)