#Vitest - Mocking fetch

1 messages ยท Page 1 of 1 (latest)

willow sphinx
#

Hey, I'm using vitest for my testing and I'd like to mock my fetch requests. I found https://www.npmjs.com/package/vitest-fetch-mock and it works fine, but TypeScript is unable to find the correct types. I added a global.d.ts and included it in my tsconfig.json, but TypeScript still complains about using fetch and fetch.resetMocks() for example. Anyone got an idea for me?

tidal sigil
#

you could do something like this:

import { Mocked } from 'vitest';

const mockedFetch = fetch as Mocked<typeof fetch>;

Now you can call mock methods on the mockedFetch object and TS won't complain.

willow sphinx
tidal sigil
willow sphinx
willow sphinx
#

Okay I seem to be too stupid for this. How the hell do I mock fetch correctly? I even tried this approach now https://runthatline.com/how-to-mock-fetch-api-with-vitest/ but if I do global.fetch = vi.fn() I can't access fetch.mockResolvedValue. Same if I do const mockedFetch = fetch as Mocked<typeof fetch>; - mockResolvedValue isn't accessible. I don't get it ๐Ÿ˜…

tidal sigil
#

After you do const mockedFetch = fetch as Mocked<typeof fetch>; you are calling the mock methods (eg. mockResolvedValue) on mockedFetch right?

willow sphinx
#

Yes, I'm just doing:

import { beforeEach, describe, expect, it, vi, Mocked } from "vitest";
import { fetchToken } from "./service";

const mockedFetch = fetch as Mocked<typeof fetch>;

describe("graph api", () => {
  it("it should fetch a token", async () => {
    mockedFetch.mockResolvedValue("test")
    const data = await fetchToken("refreshToken", true);
    console.log(data);
  });
});

I'm getting:

Property 'mockResolvedValue' does not exist on type 'Mocked<(input: RequestInfo | URL, init?: RequestInit | undefined) => Promise<Response>>'.ts(2339)

If I run the actual test I get an error: TypeError: mockedFetch.mockResolvedValue is not a function.

#

Maybe I messed my tsconfig up? I'm so lost on this one sorry ๐Ÿ˜“

tidal sigil
#

I'm sorry, you are right. It does not tell TS that the actual object is a mock, but that its properties are.
So this works:

const mockedGlobal = global as Mocked<typeof global>;
mockedGlobal.fetch.mockReset();

or this:

vi.mocked(fetch).mockReset()

// or

const mockedFetch = vi.mocked(fetch);

Sorry for wasting your time ๐Ÿ™ˆ

willow sphinx
#

OHHHH

#

THANK YOU SO MUCH!!!!!

#

You are my hero ๐Ÿฅณ

#

Now I finally got everything together to test all the things I coded too hastily in the past 6 months lol

tidal sigil
#

Glad I could help!

#

Happy testing!

willow sphinx
#

Thank you so much! ๐Ÿ™‚

#

I'm sorry but I think I jumped too the wrong conclusion here too quickly, sorry! ๐Ÿ˜‚ IntelliSense / VSCode / Typescript (?) is now recognizing the functions correctly and not complaining anymore, but when I run the actual tests I'm still getting a message stating that the function doesn't exist, e.g.:

import { beforeEach, describe, expect, it, vi, Mocked } from "vitest";
import { fetchToken } from "./service";

const mockedFetch = vi.mocked(fetch);
const mockedGlobal = global as Mocked<typeof global>;
mockedGlobal.fetch.mockReset();

describe("graph api", () => {
  it("it should fetch a token", async () => {
    mockedGlobal.fetch.mockResolvedValue({ ok: false } as unknown as Response);
    mockedFetch.mockResolvedValue({ ok: false } as unknown as Response);
    const data = await fetchToken("refreshToken", true);
    console.log(data);
  });
});
TypeError: mockedGlobal.fetch.mockResolvedValue is not a function
 mockedFetch.mockResolvedValue is not a function
#

now this:

global.fetch = vi.fn();

const mockedFetch = vi.mocked(fetch);

describe("graph api", () => {
  it("it should fetch a token", async () => {
    mockedFetch.mockResolvedValue({ ok: true } as unknown as Response);
    const data = await fetchToken("refreshToken", true);
    console.log(data);
  });
});

Seems to work. I'm not sure what I'm doing here though. I'm overwriting the global fetch function with a spy? And then I'm using mocked, which just returns fetch?

#
global.fetch = vi.fn();

would be sufficient though, right? The test runs as expected then, but IntelliSense is giving up again

tidal sigil
#

vi.mocked just returns the passed argument as-is but with a different type. So you do need to mock it first.
So you need 2 things. Overwrite fetch with vi.fn(). This does the actual mocking. Then you tell TS that fetch is mocked with eg. vi.mocked.