testdouble.js: Using testdouble esm loader with ts-node/esm loader on mocha leads to errors (Node 18.6.0)

Description

I am trying to do esm mocking using testdouble with a mixed Typescript and Javascript project, mostly following this post

Node 18.6.0 now allows for chaining of loads, and I previously needed ts-node/esm in order to recognize my Typescript files and imports.

I realize that this new feature is less than a week old, but I would appreciate support with reconciling other loaders that I would need for my es6 project (or to find a way that only requires one loader). Due to project requirements, using commonjs on runtime is not an option.

Issue

When running the following mocha command:

NODE_OPTIONS=‘–experimental-specifier-resolution=node --loader=ts-node/esm --loader=testdouble’ mocha test/.js test/.spec.ts

and any permutation thereof (removing experimental-specifier-resolution, changing the order of the --loader params)

I get the following exception

Exception in PromiseRejectCallback: node:internal/modules/esm/loader:178 return output; RangeError: Maximum call stack size exceeded Exception in PromiseRejectCallback: /Users/repos/moRepo/node_modules/ts-node/dist/esm.js:120 const { source: rawSource } = await defaultLoad(url, { ^ RangeError: Maximum call stack size exceeded at validateArgs (node:internal/modules/esm/loader:578:26)

These 4 lines repeat indefinitely:

at addShortCircuitFlag (/Users/repos/myRepo/node_modules/ts-node/src/esm.ts:409:21) at load (/Users/repos/myRepo/node_modules/ts-node/src/esm.ts:239:12) at nextLoad (node:internal/modules/esm/loader:173:28) at /Users/repos/myRepo/node_modules/ts-node/src/esm.ts:255:45

Environment

node v18.6.0 npm v.8.13.2 testdouble v.3.16.6

Example Repo

I don’t have a repo handy, but I can try to create one and add it in the future.

Code-fenced Examples

service_one.ts


export function getAllInvalidObjects(connection: Connection) {
  
 const response: string[] = service_two.getData(someString);
 ... // some transformations of response
 return response;
}

service_two.ts

// this is the function I'd like to mock when testing service_one.ts
export function getData(someString) {
  axios.get('https://endpoint.com/path?string=' + someString).then((response: any) {
   resolve(response.json);
  }
}

test.ts :

import * as td from 'testdouble';

let mock_validation_rest: any;

beforeEach(async () => {
    mock_rest = await td.replaceEsm('../src/services/service_two.js');
});

afterEach(function () {
    sandbox.restore();
    td.reset();
});

it('successfully validates with mocking, async () => {
    td.when(mock_rest.prototype.getData(td.matchers.anything())).thenResolve(mockData);

    // as long as the mock above works then this test will pass
    return service_one.getAllInvalidObjects(connection).then((response: string[]) => {
      assert.equal(3, response.length);
    });
});

package.json:

    {
      "type": "module",
      "scripts": {
         "test": NODE_OPTIONS='--experimental-specifier-resolution=node --loader=ts-node/esm --loader=testdouble' mocha test/*.js test/*.spec.ts -r dotenv/config
      }
    }

tsconfig.json:

    {
      "compilerOptions": {
         "target": "es2016",
         "module": "es6,
         "moduleResolution": "node16"
         "allowJs": true,
         "esModuleInterop": true
      },
      "ts-node": {
         "esm": true
      }
      "include": [
         "./src/**/*",
         "test/**/*/.ts",
         "test/**/*.js"
      }
    }

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 24 (4 by maintainers)

Commits related to this issue

Most upvoted comments

Hey all, sorry for the delay. I haven’t had a chance to test the fix extensively.

I did try it for a unit test or two and it looks good! Personally, I’d like to do a few more test cases before closing this, but I think this should be fixed at this point.

Found the bug! Fixing…