英文:
How to mock tRPC procedures with vitest and vitest-mock-extended on client side
问题
I'm trying to mock tRPC procedures so I don't need to run the tRPC backend application to run frontend unit tests. I've tried to use vitest-mock-extended
's mock
and mockDeep
functions. The trpc client still tries to make a request over the network, and gets a connection refused error. vitest-mock-extended
has worked for the trpc backend application.
Works with normal classes
// When userService doesn't use tRPC, it's easy to mock.
const userService = mock<UserService>();
// Works. TypeScript suggests all the test functions
userService.createUser.mockResolvedValueOnce({"name": "Fake test user"});
Doesn't work with tRPC procedures
// When using tRPC, TypeScript doesn't find mockResolvedValueOnce
const userService = mock<typeof context.services.trpcClient.userService>();
// Doesn't work. Only `query` or `mutation` is shown.
userService.createUser.mutation.mockResolvedValueOnce({"name": "Fake test user"});
userService.getUser.query.mockResolvedValueOnce({"name": "Fake test user"});
I'm using tRPC, TypeScript, vitest, and vitest-mock-extended.
mockDeep attempt example
const userService = mockDeep<typeof context.services.trpcClient.userService>>();
missionManager.createUser.mutation.mockResolvedValueOnce({...});
missionManager.createUser.query.mockResolvedValueOnce({...});
Has anyone successfully mocked trpc requests on the client side for e.g. a react/typescript application? Since tests are run by vitest, this is actually a Node/jsdom environment.
英文:
I'm trying to mock tRPC procedures so I don't need to run the tRPC backend application to run frontend unit tests. I've tried to use vitest-mock-extended
's mock
and mockDeep
functions. The trpc client still tries to make a request over the network, and get's a connection refused error. vitest-mock-extended
has worked for the trpc backend application.
Works with normal classes
// When userService doesn't use tRPC, it's easy to mock.
const userService = mock<UserService>();
// Works. Typescript suggests all the test functions
userService.createUser.mockResolvedValueOnce({"name": "Fake test user"});
Doesn't work with tRPC procedures
// When using tRPC, typescript doesn't find mockResolvedValueOnce
const userService = mock<typeof context.services.trpcClient.userService>();
// Doesn't work. only `query` or `mutation` is shown.
userService.createUser.mutation.mockResolvedValueOnce({"name": "Fake test user"});
userService.getUser.query.mockResolvedValueOnce({"name": "Fake test user"});
I'm using tRPC, typescript, vitest and vitest-mock-extended.
mockDeep attempt example
const userService = mockDeep<typeof context.services.trpcClient.userService>>();
missionManager.createUser.mutation.mockResolvedValueOnce({...});
missionManager.createUser.query.mockResolvedValueOnce({...});
Has anyone successfully mocked trpc requests on the client side for e.g. a react/typescript application. Since tests are run by vitest, this is actually a Node/jsdom environment.
答案1
得分: 4
I found msw-trpc which will allow you to use msw in a tRPC type-safe way. It works if you only use HTTPLink. Unfortunately, it doesn't support WebSockets (I use WsLink with tRPC in 1 project) so I created a Github issue. Alternatively, you could try combining mock-socket
and a wrapper class to use your tRPC AppRouter type.
They haven't documented how to use it in vitest, so here's how I do it. Install dependencies: pnpm add -D vitest vitest-mock-extended msw msw-trpc
.
How to use in tests
import { AppRouter } from "../trpc/appRouter";
import { setupServer } from "msw/node";
import { createTRPCMsw } from "msw-trpc";
import { beforeEach, describe, it, vi } from "vitest";
import { mockDeep } from 'vitest-mock-extended';
import { trpcClient } from "./trpcClient";
// You probably want to put this in a `setupTests.ts` so it runs in all tests.
vi.mock("./trpcClient", () => {
return {
trpcClient: mockDeep(),
};
});
export const trpcMsw = createTRPCMsw<AppRouter>();
// You can create the responses, and change it for each test in vitest/jest.
const server = setupServer();
// Put any handlers you want to work for all tests.
describe("Example class", () => {
beforeEach(() => {
server.resetHandlers(); // resets to the original handlers, which I did not set.
});
it("parses and loads products json into local SQLite database", async () => {
server use trpcMsw.product.getProduct.query(async (req, res, ctx) => {
// body is deprecated in msw, but the alternative req.json() is not typed...
// const body = await req.json();
// Do something with body.
const body = req.body;
return res(ctx.status(200), ctx.data(undefined));
})
);
// Run some code, then run assertions.
});
// more tests...
});
英文:
I found msw-trpc which will allow you to use msw in a tRPC type-safe way.
It works if you only use HTTPLink. Unfortunately, it doesn't support WebSockets (I use WsLink with tRPC in 1 project) so I created a Github issue. Alternatively, you could try combining mock-socket
and a wrapper class to use your tRPC AppRouter type.
They haven't documented how to use it in vitest, so here's how I do it. Install dependencies: pnpm add -D vitest vitest-mock-extended msw msw-trpc
.
How to use in tests
import { AppRouter } from "../trpc/appRouter";
import { setupServer } from "msw/node";
import { createTRPCMsw } from "msw-trpc";
import { beforeEach, describe, it, vi } from "vitest";
import { mockDeep } from 'vitest-mock-extended';
import { trpcClient } from "./trpcClient";
// You probably want to put this in a `setupTests.ts` so it runs in all tests.
vi.mock("./trpcClient", () => {
return {
trpcClient: mockDeep(),
};
});
export const trpcMsw = createTRPCMsw<AppRouter>();
// You can create the responses, and change it for each test in vitest/jest.
const server = setupServer();
// Put any handlers you want to work for all tests.
describe("Example class", () => {
beforeEach(() => {
server.resetHandlers(); // resets to the original handlers, which I did not set.
});
it("parses and loads products json into local SQLite database", async () => {
server.use(
trpcMsw.product.getProduct.query(async (req, res, ctx) => {
// body is deprecated in msw, but the alternative req.json() is not typed...
// const body = await req.json();
// Do something with body.
const body = req.body;
return res(ctx.status(200), ctx.data(undefined));
})
);
// Run some code, then run assertions.
});
// more tests...
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论