Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

connect-node client does not support mocking with MSW #1325

Closed
mykhailo-hrynko opened this issue Nov 6, 2024 · 2 comments
Closed

connect-node client does not support mocking with MSW #1325

mykhailo-hrynko opened this issue Nov 6, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@mykhailo-hrynko
Copy link

HTTP requests made with connect-node transport are not intercepted with MSW.

I have a ConnectRPC server running the default ElisaService.

Another Node.js app is using it via connect-node transport. In order to write func tests I need to mock all external HTTP requests.

I use MSW lib for mocking (See the code below).

The main issue is that connect-node requests are not intercepted, because of the way node:http module is imported in the connect-es/packages/connect-node.

The simplest code to reproduce the problem:

import { createClient } from "@connectrpc/connect";
import { createConnectTransport } from "@connectrpc/connect-node";
import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";

const BASE_URL = "Connect server URL";
const API_URL = BASE_URL + "path to your ElisaService/Say";

const handler = http.post(API_URL, () => HttpResponse.json({ sentence: "42" }));
const server = setupServer(handler);
server.listen({ onUnhandledRequest: "error" });

const transport = createConnectTransport({
  baseUrl: BASE_URL,
  httpVersion: "1.1",
  useBinaryFormat: false,
});

const client = createClient(ElisaService, transport);
const res = await client.say({ sentence: "Hello" });

console.log(res.sentence); // should be 42

Environment:

  • @connectrpc/connect-node version: 1.6.1
  • Node.js version: (for example, 20.17.0)
@timostamm
Copy link
Member

The example you give for mocking the RPC Say would probably work, but it has several downsides:

  • It only works for JSON, not for binary requests
  • It is very impractical to mock the message enveloping that gRPC, gRPC-web, and Connect (with streaming RPCs) use
  • It does not support HTTP/2
  • The JSON response is not type-safe
  • It does not support cancellation and timeouts
  • It's not trivial to mock errors

Have you seen our documentation for testing? createRouterTransport solves all of the problems above, you only need to inject the transport into the code under test.

If the problems do not affect you, there's another simple solution: You can use a transport from @connectrpc/connect-web, which simply uses fetch under the hood. If I'm not mistaken, msw can intercept fetch calls reliably, so this should allow you to mock with msw.

@mykhailo-hrynko
Copy link
Author

mykhailo-hrynko commented Nov 6, 2024

@timostamm Thank you for quick response&

My situation is that I have 2 microservices communicating via connect. And I need to test the client. So in these test I don't control how the server is configured. I just want to mock external calls.

Also as it is a functional test I don't want to inject anything instead of real code into my app.

I'll try with connect-web. Thanks!

UPD:
Using connect-web instead of connect-node for the transport seems to work correctly with MSW. Closing the issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants