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

使用Sinon Mock含同名命名空间的FastGlob库函数时遇到问题如何解决?

解决方法

问题根源

fast-glob 采用了 TypeScript 中函数与同名命名空间合并的特性,最终 export = FastGlob 导出的本身就是可调用的函数实体,命名空间下的sync/stream等成员是直接挂载在这个函数对象上的属性,不存在名为FastGlob的子属性,所以你之前尝试stub(FastGlob, "FastGlob")的写法自然无法匹配。
同时 TypeScript 的类型系统对这种合并导出做了特殊处理,默认只能识别到命名空间的属性,无法直接识别该对象本身是可被 stub 的函数,需要用类型断言绕开检查。

正确 Mock 写法

方案1:使用 proxyquire 替换模块(无额外框架依赖)

这是最稳妥的方式,不会受 ES 模块导入只读的限制:

import sinon, { SinonStub } from 'sinon';
import proxyquire from 'proxyquire';
import { Pattern, Options } from 'fast-glob';

// 1. 创建目标重载的 stub
const globStub: SinonStub<[source: Pattern | Pattern[], options?: Options], Promise<string[]>> = sinon.stub();
// 模拟返回你需要的结果
globStub.resolves(['/test/file1.ts', '/test/file2.ts']);

// 2. 加载业务代码时替换 fast-glob 依赖
const yourBusinessModule = proxyquire('./你的业务代码文件路径', {
  'fast-glob': globStub
});

// 3. 后续正常执行测试逻辑即可

如果需要保留命名空间下的其他方法(比如sync)不被 mock,只要把原模块的静态属性复制到 stub 上即可:

const originalFastGlob = require('fast-glob');
Object.assign(globStub, originalFastGlob);

方案2:直接类型断言绕开检查

如果不想引入 proxyquire,也可以通过类型断言强制修改导入对象:

import * as FastGlob from 'fast-glob';
import sinon, { SinonStub } from 'sinon';
import { Pattern, Options, Entry } from 'fast-glob';

// 断言 FastGlob 为可修改的函数对象,stub 其调用
const globStub = sinon.stub(
  FastGlob as unknown as { (source: Pattern | Pattern[], options?: Options): Promise<string[] | Entry[]> },
).resolves(['/test/file1.ts']);

// 测试调用
const res = await FastGlob('./my/glob/**/*.ts', { absolute: true });
console.log(res); // 输出模拟的 ['/test/file1.ts']

重载匹配说明

如果需要模拟不同的重载返回,只要给 stub 加条件判断即可,比如匹配objectMode为true的参数时返回 Entry 数组,否则返回字符串数组:

globStub.callsFake(async (source, options) => {
  if (options?.objectMode) {
    return [{ path: '/test/file1.ts' } as unknown as Entry];
  }
  return ['/test/file1.ts'];
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:54:01