如何在不修改解构导入写法的前提下用Sinon stub模块导出的独立函数
解决方案
可以实现,不需要修改现有业务代码的解构导入写法。
原写法失效原因
file.js中对fun的解构导入会在模块加载阶段执行,直接将code.js导出对象中fun的原始引用拷贝到file.js的内部作用域。你原有测试代码的执行顺序是先加载file.js完成拷贝,再对code.js的导出对象做stub,此时修改的只是导出对象的属性,不会影响file.js内部已经保存的原始函数引用,因此stub不生效。
实现方案1:调整加载顺序 + 清理模块缓存
仅需修改测试代码执行顺序,在加载file.js前先完成打桩,同时清理模块缓存避免缓存影响,示例代码如下:
const sinon = require('sinon'); const code = require('./code'); it('Should return Some Message', () => { // 先完成打桩 const stubFun = sinon.stub(code, 'fun').returns(true); // 清理file模块的缓存,确保重新加载时拿到最新的stub引用 delete require.cache[require.resolve('./file')]; // 再加载file模块,此时解构拿到的就是已经打桩后的函数引用 const abc = require('./file'); // 执行测试逻辑 abc.abc(); // 可选:验证stub调用符合预期 sinon.assert.calledOnce(stubFun); // 测试完成后恢复原函数,避免影响其他用例 stubFun.restore(); });
如果有多个测试用例需要打桩,可以将清理缓存、加载模块的逻辑放到beforeEach钩子中统一处理。
实现方案2:搭配proxyquire做依赖替换
借助轻量依赖注入工具proxyquire,可以在不修改业务代码的前提下,直接替换file.js加载的依赖项,示例代码如下:
const sinon = require('sinon'); const proxyquire = require('proxyquire'); it('Should return Some Message', () => { // 构造stub const stubFun = sinon.stub().returns(true); // 加载file模块时,替换它依赖的./code模块的导出 const abc = proxyquire('./file', { './code': { fun: stubFun } }); // 执行测试逻辑 abc.abc(); // 验证stub调用符合预期 sinon.assert.calledOnce(stubFun); });
内容的提问来源于stack exchange,提问作者Vaibhav Solanki
相关产品推荐
相关产品推荐

