Javascript 在此模块外模拟Node.js模块中的构造函数(或其他函数)
我使用Jasmine来编写测试,但我想任何其他测试框架都会有这个问题。假设我们有一个模块Javascript 在此模块外模拟Node.js模块中的构造函数(或其他函数),javascript,unit-testing,node.js,tdd,mocking,Javascript,Unit Testing,Node.js,Tdd,Mocking,我使用Jasmine来编写测试,但我想任何其他测试框架都会有这个问题。假设我们有一个模块foo,有两个函数,Bar和Baz,它们是构造函数(但可能只是普通函数): 现在我想测试一下Bar,但是使用了一个假的Baz实现: var foo = require('foo'); describe("foo.Bar", function() { it("initializes its own Baz", function() { spyOn(foo, 'Baz'); // this repl
foo
,有两个函数,Bar
和Baz
,它们是构造函数(但可能只是普通函数):
现在我想测试一下Bar
,但是使用了一个假的Baz
实现:
var foo = require('foo');
describe("foo.Bar", function() {
it("initializes its own Baz", function() {
spyOn(foo, 'Baz'); // this replaces foo.Baz with a fake implementation
var bar = new foo.Bar();
expect(foo.Baz).toHaveBeenCalled();
});
});
问题是该测试将失败,因为Bar
使用变量Baz
实例化了一个新的Baz
,该变量不能从外部更改。使用spyOn()
交换的唯一东西是exports.Baz
显而易见的解决方案是编写
this.baz=newexports.baz()代码>但感觉有点尴尬。如果我想在模块中使用更多的函数,我必须始终使用exports.
前缀调用所有函数。这里还有其他方法吗?如果您能以某种方式将这两个类解耦,比如允许Baz类的其他实现提供给bar,那么我认为这是最好的方法,您应该这样做
但是,如果您真的希望能够将exports.Baz
引用为Baz
,那么我可以想到一种方法,将与一起使用
据说将与
一起使用通常是一种不好的做法,应该避免,我不会在自己的代码中使用它,但这是解决问题的一种方法,甚至可以,只要您知道自己在做什么
下面是:
with(exports) {
exports.Bar = function Bar() {
console.log('this is bar!');
this.baz = new Baz();
};
exports.Baz = function Baz() {
console.log('original baz!');
};
}
在另一个模块中,如果您将foo.Baz
更改为其他内容,foo内部的Baz
也将查找它
我仍然建议找到一种使这两个类相互独立的方法,然后您可以给Baz任何您想要的实现。尝试spyOn(window'Baz')
和'expect(window.Baz).toHaveBeenCalled();'@Prusse,我想Node没有窗口
对象。对不起,如果有全局对象,您可以在适当的位置使用它。@Prusse,恐怕我不明白。什么是全局对象?难道没有一个关于没有全局对象的模块系统吗?将与
一起使用很有意思,但我想这太不规范了。我不希望将这两个“类”解耦,因为Baz
从未在Bar
之外实例化过。您可以说,也许我不应该测试Baz
,因为这是一个内部实现细节,但实际上整个系统的行为非常复杂,我需要更细粒度的测试。无论如何,谢谢你的提示。
with(exports) {
exports.Bar = function Bar() {
console.log('this is bar!');
this.baz = new Baz();
};
exports.Baz = function Baz() {
console.log('original baz!');
};
}