You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node ES Modules环境下如何用Sinon.js stub导出为函数的外部库

解决方案

失效原因

原有写法不生效的核心原因有两个:

  1. Sinon的stub仅支持替换对象上的属性方法,直接传入函数作为参数时,无法替换其他模块中对原始函数的引用
  2. Node ES Modules的导入绑定是只读的,直接修改导入的默认导出变量不会生效

方案1:最小修改业务代码(无额外依赖)

仅需在内部业务代码中新增一个可访问的依赖挂载对象,无需修改外部库、无需引入额外测试依赖,非常适合仅少量函数需要测试的场景。

  1. 修改mathProblems.js代码:
import sum from 'externalSum'

// 新增可导出的依赖挂载对象
export const deps = {
  sum
}

export function sumMore1(a) {
  // 调用挂载对象上的方法,而非直接调用导入的函数
  return deps.sum(a, 1);
}
  1. 修改测试文件spec.js代码:
import sinon from 'sinon'
import assert from 'assert'
import { sumMore1, deps } from '../mathProblems.js'

describe('sumMore1 is working', () => {
  let sumStub
  // 每次测试前创建stub
  beforeEach(() => {
    sumStub = sinon.stub(deps, 'sum')
  })
  // 每次测试后恢复原始方法,避免用例互相影响
  afterEach(() => {
    sumStub.restore()
  })

  it('sumMore1 test', () => {
    sumStub.withArgs(1, 1).returns(2)

    const result = sumMore1(1)
    assert.strictEqual(result, 2)
    // 可额外验证调用符合预期
    assert.ok(sumStub.calledOnceWith(1, 1))
  });
});

方案2:不修改业务代码(轻量依赖方案)

如果完全不想改动业务代码,可以使用专门为ESM设计的轻量mock库esmock,无需模拟CommonJS的require逻辑,配置成本极低。

  1. 安装依赖:
npm install esmock --save-dev
  1. 修改测试文件spec.js代码:
import sinon from 'sinon'
import assert from 'assert'
import esmock from 'esmock'

describe('sumMore1 is working', () => {
  it('sumMore1 test', async () => {
    const sumStub = sinon.stub().withArgs(1, 1).returns(2)
    // 导入业务模块时直接替换外部依赖的导出
    const { sumMore1 } = await esmock('../mathProblems.js', {
      'externalSum': sumStub
    })

    const result = sumMore1(1)
    assert.strictEqual(result, 2)
  });
});
  1. 运行测试时添加加载器参数即可:
node --loader=esmock node_modules/mocha/bin/mocha spec.js

内容的提问来源于stack exchange,提问作者KevynTD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 14:09:03