简体   繁体   English

在此模块外部的Node.js模块中模拟构造函数(或其他函数)

[英]Mocking a constructor (or other function) in a Node.js module outside of this module

I'm using Jasmine to write my tests, but I guess I'd have this problem with any other testing framework. 我正在使用Jasmine编写我的测试,但我想我对任何其他测试框架都有这个问题。 Let's say that we have a module foo with two functions, Bar and Baz , which are constructors (but could be just normal functions): 假设我们有一个带有两个函数的模块fooBarBaz ,它们是构造函数(但可能只是普通函数):

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: 现在我想测试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();
  });
});

The problem is that this test will fail, because Bar instantiates a new Baz using the variable Baz , which cannot be changed from outside. 问题是,这个测试将失败,因为Bar实例化一个新Baz使用变量Baz ,不能从外部改变。 The only thing that got swapped by using spyOn() is exports.Baz . 这得到了通过交换的唯一的事情spyOn()exports.Baz

The obvious solution is to write this.baz = new exports.Baz(); 显而易见的解决方案是编写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. 如果我想在模块中使用更多函数,我必须始终使用exports.调用所有函数exports. prefix. 字首。 Is there any other approach here? 这里有其他方法吗?

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. 如果你能以某种方式解耦这两个类,比如允许Baz类的其他实现被赋予bar,那么我认为这是最好的方法,你应该去实现它。


But if you really want to be able to be able to refer to exports.Baz as Baz , then there's one way that I could think of, using with . 但如果你真的希望能够能够参考exports.BazBaz ,再有就是,我能想到的,使用一种方式with

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. 据说使用with通常是一种不好的做法,应该避免,我不会在我自己的代码中使用它,但这是解决它的一种方法,甚至可以是一个有效的用途 ,只要你知道你是什么是做。

Here it goes: 在这里:

with(exports) {

    exports.Bar = function Bar() {
        console.log('this is bar!');
        this.baz = new Baz();
    };

    exports.Baz = function Baz() {
        console.log('original baz!');
    };

}

In another module if you change foo.Baz to something else, Baz inside foo will also look up to it. 在另一个模块中,如果你将foo.Baz更改为其他内容,那么foo中的Baz也会查找它。

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. 我仍然建议找到一种方法让这两个类彼此独立,然后你可以给Bar,无论你想要什么Baz的实现。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM