trpc icon indicating copy to clipboard operation
trpc copied to clipboard

Ability to add mocking of a tRPC server

Open KATT opened this issue 3 years ago • 10 comments

Summary

  • Add the ability to easily mock a tRPC backend for usage in things like storybook, jest, etc

Background

There are many use cases for mocking beyond "writing to a database.

Two that immediately come to mind for our use case:

  1. Using a mock API for stories (Storybook, Ladle). For this use case, even if we could use a real endpoint, it wouldn't be a good idea, as one generally wants to control the data and not have some gibberish mock data created by test users.
  2. Endpoints that go beyond database calls. We have a use case that requires a tight integration with many AWS services, including ones that would bill you a lot, if you were just creating these resources for testing. In this case also running a live API isn't even feasible locally. And deploying an actual API can take many minutes. So you can't even tear it down for each test.

I agree on integration > mocking premise in general. But there are some cases that are just not feasible without having mocks.

Originally posted by @moltar in https://github.com/trpc/trpc/discussions/1879#discussioncomment-3395657

Todos

  • [ ] Create spec/RFC on how mocking should look like
  • [ ] Implement said mocking

T-75

Funding

  • You can sponsor this specific effort via a Polar.sh pledge below
  • We receive the pledge once the issue is completed & verified
Fund with Polar

KATT avatar Aug 16 '22 10:08 KATT

Create spec/RFC on how mocking should look like

Could this work?

Add an optional option.mock parameter to each function (api) returning from createTRPCProxyClient, the option.mock type should be the same as the return type form the function (api).

Example: import { setMock, createTRPCProxyClient } from "trpc/client";

const client = createTRPCProxyClient<AppRouter>({url, allowMocks: process.env.node_env != "production" );

// setting the mock for /posts setMock(client.posts, [{ id: 1, content: "post 1"}]);

Something like that?

yaniv-peretz avatar Sep 16 '22 13:09 yaniv-peretz

@Yanipo5 @KATT I think mocking would be easy now that HTTP is decoupled from the client. One can create a mockLink that simply intercepts all requests. For example, maybe can use PollyJS for that.

moltar avatar Sep 16 '22 14:09 moltar

I don't exactly understand that firm statement about testing. Intercepting and stubbing calls is super useful when working on the front end. You can quickly set up various cases and store all the code in the git repo.

marekbrze avatar Oct 26 '22 17:10 marekbrze

I personally don't see the value in putting this into tRPC proper. I think it serves the library to keep it lean and recommend / provide examples for something like https://mswjs.io/

VinSpee avatar Nov 28 '22 12:11 VinSpee

@KATT I agree it should be implemented.

For sure it's possible to hack in tests with Jest by trying to spyOn... but in some cases with want mocks at runtime. In my case I ended using msw to mock what the trpc could answer, but that's a real pain to think about network response format to be sure the tRPC client will be fine.

I think a trpc client middlewares logic could do the trick. When I would want the mock, I add a middleware at the first position, I do my "switch case" or whatever to have the consistent behavior and just return the needed result. In this case the middleware would not call the next() middleware, but still, it would allow people to do any trick they want.

The perfect solution and the more agnostic would be to wrap the trpc logic in a custom data repository that is easy to mock at initialisation... but since it's easier to use trpc with react-query sometimes, it makes things to complicated too go this way (since the React logic would be coupled with the repository in case of @trpc/react...).

sneko avatar Dec 09 '22 17:12 sneko

@sneko could you share how you managed to mock it using msw? I tried with a rest handler but the trpc query is not intercepted

nicotsx avatar Dec 19 '22 22:12 nicotsx

@meienberger it's currently spread across my project :s , but for reference I can advise you:

It was inspired by: https://gist.github.com/martin-fv/9bad75363245a16c918e112eb6a19f0d

The issues to follow for future improvements: https://github.com/trpc/trpc/discussions/1879 https://github.com/trpc/trpc/issues/2468 (this one :D )

sneko avatar Dec 19 '22 22:12 sneko

@sneko thank you for sharing!

nicotsx avatar Dec 19 '22 23:12 nicotsx

https://github.com/maloguertin/msw-trpc

KATT avatar May 24 '23 23:05 KATT

Is https://github.com/maloguertin/msw-trpc the way to go for integrating storybook with trpc?

fmonper1 avatar Jan 15 '24 19:01 fmonper1