Closed TheHolyWaffle closed 2 months ago
Hi, @TheHolyWaffle. Thanks for reporting this.
Please, compare your usage example to the Jest and Jest+JSDOM examples from MSW. Those are functional (as functional as anything on JSDOM can get).
You don't have to import fetch
from undici explicitly if you have this line.
I also highly recommend to drop jest.polyfills.js
and use jest-fixed-jsdom preset instead. Try that and let me know if you still encounter the issue.
@kettanaito Thanks for looking into this.
I have removed the polyfills again in the minimal reproduction. They were a futile attempt to fix my issue but they never made sense. This bug purely revolves around a nodejs backend microservice, no jsdom environment is needed.
I have a hard requirement to import fetch
directly from the undici
package. This is because the node built-in version of fetch
is from an older undici
version. Since then, there have been bugs fixed in undici
. Also, the node built-in fetch does not allow passing a dispatcher
directly, unlike fetch
from undici
. Because of these reasons, I cannot use the global fetch
.
Please reconsider this issue 🙏
I have a hard requirement to import fetch directly from the undici package.
That shouldn't be a problem.
Also, the node built-in fetch does not allow passing a dispatcher directly, unlike fetch from undici.
TIL!
No worries, let's reopen this then.
@TheHolyWaffle we have exactly the same reasons to use undici
instead of the Node's native fetch
: the dispatcher
. And the same problem, that MSW does not intercept and mock the requests, but let's the requests go through to the real service.
Have you found a decent solution?
@bobanm I went ahead with Undici's MockAgent
instead of msw
, see https://undici.nodejs.org/#/docs/api/MockAgent
Feel free to 👍 the original issue to bring more attention to this!
@TheHolyWaffle I ended up doing the same. I find it to be a little bit less elegant than using MSW, but still quite a good solution.
I hope MSW adds support for Undici.
@TheHolyWaffle Are you sure that node's fetch does not support the dispatcher field? I have the same problem, but as far as I understand, the issue is with TS types, not in the API of the native fetch. At least the typings for the "node version of the types" do include the dispatcher
field in the RequestInit
object.
https://github.com/DefinitelyTyped/DefinitelyTyped/pull/66824
If you are using typescript, the @types/node
library may be giving you the DOM types when you'd prefer to use the types for node ("undici types"). If your TS project includes a frontend, you may have configured lib.dom.d.ts
in use yourself ("lib": ["dom"]
in tsconfig
) or a dependency of yours may be pulling it in (you can try to use explainFiles to find out the cause(s) of the files inclusion if its unclear).
This may be of no real help to you. Just jotting this down for future reference in case it has an impact on API decision. Still looking for a feasible workaround myself.
E: At least one workaround is to use multiple tsconfig
files and structure your project so that the fetch
integration is covered by a tsconfig
without lib.dom.d.ts
and any dependencies that may end up including it.
Undici is a custom client that doesn't rely on the node:http
module, which is a primary request-issuing module which MSW observes in Node.js (as of now). Because of that, the requests Undici makes are invisible to MSW (I believe Undici uses net.Socket
directly).
For now, you can switch to Undici's MockAgent
as Undici ships with their own mocking in mind. If that works for you, that's great!
Note that you can call MSW request handlers directly, including in your
MockAgent
by Undici. See thegetResponse()
function.
MSW has a strong position on not shipping request client-specific code. Instead, we try out best to support the underlying protocols, tapping into the network at the layer that is both more resilient and less intrusive to the things you are running.
I highly doubt a standalone Undici support will ever happen in MSW. What may happen, is net.Socket
support, which Undici uses. We've already merged the Socket-based interceptor in @mswjs/interceptors
but (a) it's not used in MSW yet; (b) it still taps into node:http
by using a custom Agent
and a mock socket.
Raw socket-level interception is theoretically possible, we just need to get it right. Sockets transport many things, not just HTTP requests. We better not interfere with those things.
[!IMPORTANT] Also please note that MSW supports global
fetch
in Node.js still. That is also, technically, Undici. It just has to be a globalfetch
function. It's important to disambiguate that we aren't talking about globalfetch
but about a standalone usage of Undici, like theirrequest
function.
There's no plans to add raw Socket-level interception to support the direct usage of Undici. Please refer to my response above to see how you can fix it in your app.
You can also expose Undici's fetch globally as a part of your setup and have the interception working.
Prerequisites
Environment check
msw
versionNode.js version
20.13.1
Reproduction repository
https://github.com/TheHolyWaffle/msw-undici-reproduction
Reproduction steps
npm i
npx jest
to run the sampletest.js
unit testCurrent behavior
When adding a GET handler to
https://example.com
,msw
does not intercept the request. Instead thefetch
goes to the real example.com. See failing unit test.To make the unit test succeed, uncomment
const { fetch } = require("undici");
so that the node-native fetch is used instead of the `Expected behavior
msw
should intercept thefetch
call fromundici
and unit test should succeed.