You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I am currently working on a project using Node 18, TypeScript 4.8, purely ESM written using .mts files and the Mocha + Chai + Sinon test framework.
I have a very simple code to test that sets a header to a ServerResponse object and then pipes it through zlib to enable Gzip compression.
The code is as follows:
// import type { IncomingMessage } from "http";import{ServerResponse}from"node:http";import{createGzip}from"node:zlib";importtype{Gzip}from"node:zlib";importtype{HTTPStatusCodeEnum}from"../HTTP/HTTPStatusCodeEnum.mjs";classResponseextendsServerResponse{privatecontent: string="";/** * send */publicsend(content?: string|Buffer|undefined): void{this.setHeader("Content-Encoding","gzip");console.debug("called");// @TODO: Make response compression great againconstENCODER: Gzip=createGzip();ENCODER.pipe(this);ENCODER.write(content??this.content);ENCODER.end();}/** * getContent */publicgetContent(): string{returnthis.content;}/** * setContent */publicsetContent(content: string): void{this.content=content;}/** * setStatusCode */publicsetStatusCode(status_code: HTTPStatusCodeEnum): void{this.statusCode=status_code;}}export{Response};
This is part of a class Response that extends ServerResponse. The class does work as intended and has been used successfully even in production.
I wanted to rewrite my entire test base to use the configuration I explained before.
I then realized that ES modules cannot be stubbed using Sinon since that are locked.
I stumbled upon this library that seemed to be exactly what I needed. I briefly considered Proxyquire but it seems to only work with require and nothing else.
/* eslint-disable @typescript-eslint/no-unused-expressions, @typescript-eslint/no-empty-function, max-len, max-lines-per-function */import{IncomingMessage}from"node:http";import{Socket}from"node:net";import{expect}from"chai";importesmockfrom"esmock";import{Response}from"../../../../src/main/Web/Server/Response.mjs";awaitesmock("../../../../src/main/Web/Server/Response.mts",import.meta.url,{zlib: {createGzip: {pipe: ()=>{console.debug("pipe called 2");}}}});describe("Response",(): void=>{describe("send",(): void=>{it("should call the Gzip.pipe functions from the zlib native module",(): void=>{constSOCKET: Socket=newSocket();constINCOMING_MESSAGE: IncomingMessage=newIncomingMessage(SOCKET);constRESPONSE: Response=newResponse(INCOMING_MESSAGE);RESPONSE.send("Test");expect(PIPE_STUB.called).to.be.true;// Irrelevant as I previously tried to use SinonStubs (which are still in the test but I removed them from this sample since they are never called anywhere. This expect will always fail but this is not my problem.});});});
The thing is, whilst running the test, it properly prints "called" from the send method, but it never prints "pipe called 2" from the mocked module.
I have been scratching my head why for some time now and I have honestly no idea what's going on. I do not get any error from esmock with this syntax. If I change the module path to use the .mjs extension I get an invalid module id error. This means the .mts extension syntax seems to be correct but somehow, the module simply isn't mocked.
I believe I am missing something here. Could you help me solve this issue please? 🙏
Thanks! ❤️
The text was updated successfully, but these errors were encountered:
@SmashingQuasar thanks for opening this issue. Two things, one: only the esmock-returned Response will use the mocked import tree and so that is the Response definition that should be used in the test,
The other thing is that esmock's scripted resolver might not handle the 'mts' extension correctly. If that's the case, run the test process with --experimental-import-meta-resolve to use node's native resolver. If --experimental-import-meta-resolve is needed, please open an issue here and I'll resolve the scripted resolver issue :)
Actually I figured out what I was doing wrong just before I read your answer. It was indeed because I was not using the returned mocked module and was attempting to use the native one. I probably misread the documentation, my bad!
It works perfectly using .mts and Sinon. Thanks for your work, this library works like a charm, it totally solved my issue!
It's unfortunate that the syntax is this heavy but I understand there is most likely no other way to do this as of today.
Hey!
I am currently working on a project using Node 18, TypeScript 4.8, purely ESM written using
.mts
files and the Mocha + Chai + Sinon test framework.I have a very simple code to test that sets a header to a
ServerResponse
object and then pipes it throughzlib
to enable Gzip compression.The code is as follows:
This is part of a class
Response
that extendsServerResponse
. The class does work as intended and has been used successfully even in production.I wanted to rewrite my entire test base to use the configuration I explained before.
I then realized that ES modules cannot be stubbed using Sinon since that are locked.
I stumbled upon this library that seemed to be exactly what I needed. I briefly considered Proxyquire but it seems to only work with
require
and nothing else.Here is my
.mocharc.json
file:Here is the
tsconfig.json
file used for testing:Here is the test that I wrote:
The thing is, whilst running the test, it properly prints "called" from the
send
method, but it never prints "pipe called 2" from the mocked module.I have been scratching my head why for some time now and I have honestly no idea what's going on. I do not get any error from
esmock
with this syntax. If I change the module path to use the.mjs
extension I get an invalid module id error. This means the.mts
extension syntax seems to be correct but somehow, the module simply isn't mocked.I believe I am missing something here. Could you help me solve this issue please? 🙏
Thanks! ❤️
The text was updated successfully, but these errors were encountered: