许多节点模块将单个函数(不是构造函数,而是通用“实用程序”函数)导出为其“module.exports”。 是否可以使用 Sinon.js 来存根这个独立的函数?
// some module, "sum.js" that's "required" throughout the application
module.exports = function(a, b) {
return a + b;
};
// test.js
var sum = require('sum');
...
beforeEach(function() {
sumStub = sinon.stub(sum);
// throws: TypeError: Attempted to wrap undefined property undefined as function
});
afterEach(function() {
sumStub.restore();
});
...
有没有办法实现这一目标?
不幸的是没有。
对于 npm,您可以使用https://github.com/thlorenz/proxyquire或类似方法。 Michael Feathers 将其称为链接接缝。
这并不优雅,但可行。
一旦你有了它,你就可以像往常一样使用Sinon。
从长远来看,您可能希望将您的架构转向 _object 接缝_,但它是今天有效的解决方案。 RequireJS 也有类似的项目。
function MyFunction(){}
module.exports = function(){ return module.exports.MyFunction.apply(this, arguments) }
module.exports.MyFunction = MyFunction
然后您可以存根 require('./MyFunction').MyFunction 并且您的其余代码将无需更改即可查看存根版本。
:dizzy: :dizzy_face: :dizzy:
前几天偶然发现了同样的事情,这就是我所做的:
const proxyquire = require('proxyquire')
const sinon = require('sinon')
const sum = sinon.stub()
const ModuleWithDependency = proxyquire('module', {
'sum': sum
})
对于我们的案例来说效果很好。
如果使用 CommonJS:
const myStubbedModule = function( absoluteModulePath ) {
const stub = sinon.stub();
require.cache[ require.resolve( absoluteModulePath ) ] = stub;
return stub;
}
_注意_:根据您是否正在转译,您可能需要执行以下操作:
require.cache[ require.resolve( absoluteModulePath ) ] = {
default: stub,
exports: stub
}
通常在测试期间,我需要为一项特定测试插入一个存根。 我采用的包装函数方法让我可以随时修改代码库并插入我的存根,而不必采用存根优先的方法或使用引用其他模块的模块玩我正在尝试的模块存根和就地更换。
我已经进行了多次代码审查,人们通过 proxyquire、 mock-require和 c 推动我在 Node 模块层进行黑客攻击,它开始很简单,看起来不那么粗鲁,但成为获取存根的一个非常困难的挑战在测试设置期间需要到位。 使用 proxyquire 至少可以使用 proxyquire() 应用程序的微型/夹具大小版本,一些顶级的东西,并且所有存根都将在加载过程中被引入,但是在 JS 语言级别而不是 Node 模块级别继续解决这个问题让我觉得更直接,更容易持续管理且没有危险(警告:只要你记得恢复)。
我使这个模块更容易存根模块https://github.com/caiogondim/stubbable-decorator.js
我只是在玩 Sinon 并找到了似乎有效的简单解决方案 - 只需添加“参数”作为第二个参数
const sumStub = sinon.stub(sum, 'arguments');
sumStub.withArgs(2, 2).returns(4);
sumStub.withArgs(3, 3).returns(6);
尝试这个
import * as sum from './sum'
sinon.stub(sum, 'default', () => {
// stubbed function
});
@harryi3t - 谢谢这对我
@harryi3t这对我不起作用,使用 ES 模块。
错误: can't redefine non-configurable property "default"
可能的解决方法
(function (defineProperty) {
Object.defineProperty = (obj, prop, desc) => {
desc.configurable = true;
return defineProperty(obj, prop, desc);
};
})(Object.defineProperty);
@Sujimoshi解决方法究竟是什么? 你修复的背景是什么? 另外,人们会把修复程序放在哪里? 在目前的版本中,它缺少的信息太多而无济于事。 它对原始问题没有帮助,也不适用于ES Modules 。 我猜它与 Webpack 4 处理过的代码有关,因为它可能适用于(取决于您的工具链)使用 ES2015+ 语法编写的代码,这些代码已_transpiled_ 到 ES5,_emulating_ES 模块通过不可配置的对象描述符的不变性.
尝试这个
import * as sum from './sum' sinon.stub(sum, 'default', () => { // stubbed function });
现在已弃用。
我刚刚从这里重写了我的 ES6 模块:
export default const doCoolStuff = () => {
// do the cool stuff...
}
对此:
export default {
doCoolStuff: () => {
// do the cool stuff...
}
}
它有点笨重,但使我能够将函数包装在存根中。
现在快2021年了,有可能吗?
现在快2021年了,有可能吗?
与2019年没有太大区别。
ES Modules 没变,CommonJS 没变,JavaScript 没变。
最有用的评论
尝试这个