TypeScript/Node中使用Sinon stub内置require函数报错如何解决
错误原因
- 抛出
Cannot stub non-existent property require是因为CommonJS规范下,require不是当前module实例的自有属性,直接对不存在的属性执行stub操作就会触发该错误。 - 代码中使用
resolves()定义返回值属于用法错误:require是同步加载方法,resolves()用于给异步方法返回Promise结果,即使stub成功,拿到的也会是Promise对象,和源码同步获取JSON对象的逻辑完全不匹配。
正确实现方案
方案1:仅用Sinon实现(无额外依赖)
Node.js 环境下,所有模块的require方法都继承自内置Module类的原型,直接stub原型上的require方法即可生效,参考代码:
const sinon = require('sinon'); const Module = require('module'); // 测试用例内 const requireStub = sinon.stub(Module.prototype, 'require'); // 匹配源码中require的路径参数,用returns返回同步mock值,禁止用resolves requireStub.withArgs('../package.json').returns({ a: 'b' }); // 其余路径的require走原生逻辑,避免拦截正常依赖加载 requireStub.callThrough(); // 在此处执行待测试函数,完成断言校验 // 示例:const res = testTargetFunc(); assert.equal(res.a, 'b'); // 测试结束必须还原原生require,避免污染其他测试用例 requireStub.restore();
注意点
withArgs传入的路径字符串必须和源码里require的参数完全一致,按字符串精确匹配,相对路径是相对于待测试文件解析,不要写成测试文件对应的相对路径。- 必须配置
callThrough(),否则所有模块加载都会被stub拦截,会导致sinon、断言库等依赖无法正常加载。 - 收尾必须调用
restore()还原原生方法,否则会导致后续测试的模块加载逻辑异常。
方案2:搭配模块mock工具实现(更稳定,推荐)
直接stub Module原型的方式如果漏写还原逻辑,容易引发全局测试异常,可以使用专门的模块依赖mock工具做作用域隔离,这类工具只会替换待测试文件内的指定依赖,不会影响全局require逻辑,也不需要手动还原。
以proxyquire为例,参考代码:
const sinon = require('sinon'); const proxyquire = require('proxyquire'); // 加载待测试文件时直接替换指定依赖 const testModule = proxyquire('待测试文件的相对路径', { '../package.json': { a: 'b' } // key和源码中require路径完全一致,value为mock值 }); // 直接调用testModule下的待测试方法做断言即可,无需额外还原操作
内容的提问来源于stack exchange,提问作者Sabo Boz
相关产品推荐
相关产品推荐

