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

TypeScript新手求助:如何用Sinon模拟模块独立函数测试

在TypeScript中用Sinon正确模拟重导出的模块方法

问题场景

现有模块结构如下:

childModule.ts

export default function go(a: number) { return a * 2 }

ParentModule.ts

export { default as go } from './childModule'

testcandidate.ts

import * as ParentModule from './ParentModule'
export function TestGo(num: number) {
  let result = ParentModule.go(num) // 修正原代码变量名重复问题
}

测试时尝试用Sinon stub ParentModule.go,但调用TestGo时依然执行原始方法:

// testcandidate.spec.ts
import { expect } from 'chai'
import * as ParentModule from './ParentModule'
import sinon from 'sinon'

// ...
let stub = sinon.stub(ParentModule,'go').retunrs(3) // 注意:这里有拼写错误,retunrs → returns

问题原因

ES模块的导出是只读绑定,ParentModule.go只是对childModule默认导出函数的引用,并非可修改的对象属性。Sinon的stub需要修改对象属性实现函数替换,因此直接stub重导出的go不会生效。

解决方案

方案1:直接Stub原始子模块(推荐,无需修改业务代码)

直接对childModule的默认导出进行Stub,因为ParentModule.go指向的是原始函数,Stub原始模块后所有引用都会生效:

// testcandidate.spec.ts
import { expect } from 'chai'
import * as ChildModule from './childModule'
import sinon from 'sinon'
import { TestGo } from './testcandidate'

describe('TestGo', () => {
  it('使用Stub的go函数并验证调用', () => {
    // Stub childModule的默认导出
    const goStub = sinon.stub(ChildModule, 'default').returns(3)
    
    TestGo(5)
    
    // 验证函数被调用1次,参数为5
    expect(goStub.calledOnceWith(5)).to.be.true
    
    // 测试结束后恢复原始函数,避免影响其他测试
    goStub.restore()
  })
})

方案2:修改ParentModule的导出结构(需调整业务代码)

将ParentModule的导出包装为一个可修改的对象,这样可以直接Stub对象上的go属性:

修改ParentModule.ts

import go from './childModule'
export const api = { go } // 导出包含go的对象

修改testcandidate.ts

import { api as ParentModule } from './ParentModule'
export function TestGo(num: number) {
  const result = ParentModule.go(num)
  return result // 返回结果方便测试断言
}

测试代码

// testcandidate.spec.ts
import { expect } from 'chai'
import { api as ParentModule } from './ParentModule'
import sinon from 'sinon'
import { TestGo } from './testcandidate'

describe('TestGo', () => {
  it('使用Stub的go函数并验证调用', () => {
    const goStub = sinon.stub(ParentModule, 'go').returns(3)
    
    const result = TestGo(5)
    
    // 断言返回值为Stub的结果
    expect(result).to.equal(3)
    // 验证调用次数和参数
    expect(goStub.calledOnceWith(5)).to.be.true
    
    goStub.restore()
  })
})

额外提示

原测试代码中的retunrs是拼写错误,正确应为returns,这个笔误也会导致Stub不生效,需要注意修正。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 10:17:22