使用 sinon 的其他 Node 开发人员如何在他们的单元测试中模拟构造函数调用?例如,假设我有一些函数 foo
function foo() {
var dependency = new Dependency(args);
// do stuff with dependency
}
exports.module.foo = foo;
在一个单独的测试文件中,我有一些测试,我想在其中验证调用依赖构造函数的内容(args),并且我需要控制它返回的内容
it('should call Dependency constructor with bar', function() {
var foo = require('myModule').foo
var DependencyMock; //code to make the mock
foo();
expect(DependencyMock.calledWith(bar)).to.equal(true);
});
问题在于 sinon 只能模拟附加到对象的函数,因此我们必须先将构造函数附加到对象才能模拟。
我一直在做的只是制作一个对象,将构造函数附加到模块中,进行构造函数调用,将构造函数作为该对象的方法调用,然后导出对象以在测试中使用它:
var Dependency = require('path/to/dependency');
var namespace = {
Dependency: Dependency
}
function foo() {
var dependency = new namespace.Dependency(args);
// do stuff with dependency
}
exports.moduole.foo = foo;
exports.module.namespace = namespace;
测试文件:
it('should call Dependency constructor with bar', function() {
var foo = require('myModule').foo;
var namespace = require('myModule').namespace;
var DependencyMock = sinon.mock(namespace, 'Dependency').returns(0);
foo();
expect(DependencyMock.calledWith(bar)).to.equal(true);
});
这行得通,但是为了测试它而在我的模块上公开一个对象感觉真的很笨拙。
有什么建议吗?
最佳答案
我认为值得一问的是为什么要模拟依赖项的构造函数而不是注入(inject)该依赖项?
考虑您的示例代码:
// in "foo.js"
function foo() {
var dependency = new Dependency(args);
// do stuff with dependency
}
exports.module.foo = foo;
如果 foo
需要 Dependency
才能工作,您可以将其作为 foo
的参数注入(inject):
// in "foo.js"
function foo(dependency) {
// do stuff with dependency
}
exports.module.foo = foo;
// in "bar.js"
var foo = require('./foo.js')(new Dependency(args));
有了这个改变,在你的测试中注入(inject)任何测试替身现在变得微不足道了(要了解更多关于 JavaScript 测试替身的信息,请查看我的 article on the subject)。
这种方法使你的函数/模块的依赖关系显式化,但需要你在某个时候将它们连接起来(这里:require('./foo.js')(new Dependency(args));
)。
如果您不想手动连接,还有另一种方法可以使用 rewire和 replacing constructor with factory method :
// in "dependency.js"
module.exports= function(args) {
return new Dependency(args);
}
// in "foo.js"
var dependency = require('./dependency');
function foo() {
var dep = dependency(args);
// do stuff with dependency
}
exports.module.foo = foo;
在你的测试中:
var rewire = require("rewire"),
foo = rewire("../lib/foo.js");
it('should call dependency... ', function() {
foo.__set__("dependency", /* some spy */ );
foo();
});
希望这对您有所帮助!
一月
关于node.js - 在 Node 中模拟构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33702588/