admin管理员组

文章数量:1122832

I'm trying to mock an ESM module using testdouble.js. Based on the example here, I attempted to replicate a similar setup whithout success using node v22.4.1.

Here's my project structure:

/src/subdep.mjs :

export function myFunction() {
    return "real subdep";
}

src/utils.mjs :

import { myFunction } from './subDep.mjs'

export function fetchData() {
    const res = myFunction();
    return `real data : ${res}`
}

__test__/test.mjs :

import { describe, test, beforeEach, it } from 'node:test';
import assert from 'node:assert';
import * as td from 'testdouble'

let subject = null
let subdep = null

describe('tests', async () => {

  // This test pass
  it('Real data', async() => {
    subject = await import('../src/utils.mjs')
    const result = subject.fetchData()

    assert.strictEqual(result, 'real data : real subdep')
    td.reset()
  });

  // this test pass
  it('Direct module mock', async() => {
    subdep = (await td.replaceEsm('../src/subdep.mjs'))
    td.when(subdep.myFunction()).thenReturn(55)
    const toto = await import('../src/subdep.mjs')

    assert.strictEqual(toto.myFunction(), 55)
    td.reset()
  });

  // this test DO not pass
  it('Indirect module mock', async() => {
    subdep = (await td.replaceEsm('../src/subdep.mjs'))
    td.when(subdep.myFunction()).thenReturn(55)

    subject = await import('../src/utils.mjs')
    const result = subject.fetchData()

    console.log(result);

    assert.strictEqual(result, 'real data : 55')
    td.reset()
  });

});

Outputs after node __test__/test.mjs

▶ tests
  ✔ Real data (1.799833ms)
  ✔ Direct module mock (53.432417ms)
real data : real subdep
  ✖ Indirect module mock (3.699834ms)
    AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
    + actual - expected

    + 'real data : real subdep'
    - 'real data : 55'
                   ^
        at TestContext.<anonymous> (file:///.../__test__/test.mjs:39:12)
        at async Test.run (node:internal/test_runner/test:857:9)
        at async Suite.processPendingSubtests (node:internal/test_runner/test:565:7) {
      generatedMessage: true,
      code: 'ERR_ASSERTION',
      actual: 'real data : real subdep',
      expected: 'real data : 55',
      operator: 'strictEqual'
    }
ℹ tests 3
ℹ pass 2
ℹ fail 1

The Problem While I can successfully mock myFunction when testing the module directly with import, the mock does not seem to take effect when testing fetchData from utils.mjs, which depends on myFunction indirectly. In the Indirect module mock test, fetchData still calls the original implementation of myFunction, instead of using the mocked return value (55).

Questions : How can I correctly mock subdep.mjs so that fetchData in utils.mjs uses the mocked version of myFunction ?

BTW, Is there some alternative to doubletest.js that can make the Indirect module mock pass ?

本文标签: nodejsHow to mock an indirect ESM dependency with testdoublejsStack Overflow