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?
#Vitest - Mocking fetch
1 messages ยท Page 1 of 1 (latest)
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.
I see, that works as a workaround, thank you, but then I also miss out on having any autocompletion at all, which is fine for the moment I guess, better than not being able to continue ๐
I've just used this method today and autocomplete works for me just fine.
You could also try this method: https://vitest.dev/api/vi.html#vi-mocked
Oh really? For me IntelliSense just gave up completely. Are you using VSCode as well? I'm using a devcontainer and I was suspecting that this might be an issue as well..
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 ๐
After you do const mockedFetch = fetch as Mocked<typeof fetch>; you are calling the mock methods (eg. mockResolvedValue) on mockedFetch right?
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 ๐
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 ๐
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
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
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.