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
相关产品推荐
相关产品推荐

