在该模块之外的 Node.js 模块中模拟构造函数(或其他函数)
我使用 Jasmine 来编写测试,但我想使用任何其他测试框架都会遇到这个问题。 我们有一个模块 foo
,它有两个函数 Bar
和 Baz
,它们是构造函数(但也可能只是普通函数):
var Bar = exports.Bar = function Bar() {
this.baz = new Baz();
};
var Baz = exports.Baz = function 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
实例化了一个新的 < code>Baz 使用变量Baz
,无法从外部更改。使用 spyOn()
唯一交换的是 exports.Baz
。
显而易见的解决方案是编写 this.baz = newexports.Baz();
但感觉有点尴尬。如果我想在模块中使用更多函数,我必须始终使用 exports.
前缀调用所有函数。这里还有其他方法吗?
I'm using Jasmine to write my tests, but I guess I'd have this problem with any other testing framework. Let's say that we have a module foo
with two functions, Bar
and Baz
, which are constructors (but could be just normal functions):
var Bar = exports.Bar = function Bar() {
this.baz = new Baz();
};
var Baz = exports.Baz = function Baz() {
};
Now I would like to test Bar
, but with a fake Baz
implementation:
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();
});
});
The problem is that this test will fail, because Bar
instantiates a new Baz
using the variable Baz
, which cannot be changed from outside. The only thing that got swapped by using spyOn()
is exports.Baz
.
The obvious solution is to write this.baz = new exports.Baz();
but it kind of feels awkward. If I have more functions which I want to use inside my module, I would have to always call all of them using the exports.
prefix. Is there any other approach here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您可以以某种方式将这两个类解耦,例如允许将 Baz 类的其他实现赋予 bar,那么我认为这是最好的方法,您应该这样做。
但是,如果您确实希望能够将
exports.Baz
引用为Baz
,那么我可以想到一种方法,即使用with< /代码>。
据说使用
with
通常是一种不好的做法,应该避免,我不会在我自己的代码中使用它,但这是解决它的一种方法,甚至可以 合法使用,只要您知道自己在做什么。事情是这样的:
在另一个模块中,如果将
foo.Baz
更改为其他内容,foo 内的Baz
也会查找它。我仍然建议找到一种方法使这两个类彼此独立,然后您可以为 Bar 提供您想要的任何 Baz 实现。
If you can somehow decouple these two classes, like allow other implementation of the Baz class to be given to bar, then I think that's the best way and you should go for it.
But if you really want to be able to be able to refer to
exports.Baz
asBaz
, then there's one way that I could think of, usingwith
.It is said that using
with
is generally a bad practice and should be avoided, I wouldn't use it in my own code, but this is one way to solve it and can even be a legimate use, as long as you know what you are doing.Here it goes:
In another module if you change
foo.Baz
to something else,Baz
inside foo will also look up to it.I would still recommend finding a way to make these two classes independent of each other and then you can just give Bar whatever implementation of Baz you want.