TypeScript中如何对模块内本地函数进行Stub?
解决TypeScript模块内函数Stub失效且保留类型安全的方案
核心思路
模块内直接调用函数时,TypeScript会编译为对函数本身的直接引用,而非模块导出对象上的方法,导致Sinon无法Stub生效。要解决这个问题,必须让模块内的函数调用指向模块导出对象的引用,同时通过类型化的引用保留类型检查能力。
方案1:自引用导入(推荐)
在模块内部通过import * as self导入自身,所有模块内跨函数调用都通过self对象进行,既保留完整类型提示,又能让Sinon的Stub逻辑生效。
模块代码示例(mymodule.ts)
import * as self from './mymodule'; export function someOtherFunc(): string { return 'original value'; } export function someFunc(): string { // 用self调用同模块函数,而非直接调用someOtherFunc() return self.someOtherFunc(); }
测试代码示例(mymodule.test.ts)
const sinon = require('sinon'); const mymodule = require('./mymodule'); const { expect } = require('chai'); describe('mymodule', () => { it('should stub someOtherFunc successfully', () => { const stub = sinon.stub(mymodule, 'someOtherFunc').returns('stubbed value'); const result = mymodule.someFunc(); expect(result).to.equal('stubbed value'); stub.restore(); }); });
方案2:类型化exports别名
如果不想使用自引用导入,可以给exports添加类型断言,将其转换为当前模块的类型,避免exports被推断为any类型。
模块代码示例(mymodule.ts)
// 定义当前模块的类型 type MyModule = typeof import('./mymodule'); // 将exports断言为模块类型,得到类型化的引用 const self = exports as MyModule; export function someOtherFunc(): string { return 'original value'; } export function someFunc(): string { // 通过类型化的self调用同模块函数 return self.someOtherFunc(); }
测试代码与方案1完全一致,Stub逻辑无需修改
方案生效原因
- 两种方案都让模块内的函数调用指向模块导出对象的引用,而非函数本身的直接绑定,Sinon Stub的是模块导出对象上的方法,因此调用时会使用被Stub后的逻辑。
- 无论是自引用导入还是类型化exports别名,都保留了TypeScript的完整类型检查,不会丢失类型安全。
内容的提问来源于stack exchange,提问作者JHH
相关产品推荐
相关产品推荐

