Javascript 用Jasmine进行单元测试,模仿构造函数

Javascript 用Jasmine进行单元测试,模仿构造函数,javascript,unit-testing,jasmine,Javascript,Unit Testing,Jasmine,我正在用Jasmine对JavaScript进行单元测试,遇到了一些问题 我有一个大文件要测试,它有很多依赖项,这些依赖项有它们自己的依赖项。因为上面提到的依赖关系,我想尽我所能去模仿。问题就在这里。如何模拟构造函数,使其包含属于它的方法 假设我正在测试类Map的方法createMap: 在createMap方法中,它使用 var layers = new Layers() 我在用电脑监视它 spyOn(window, 'Layers').and.callThrough() 这很好,但是稍后

我正在用Jasmine对JavaScript进行单元测试,遇到了一些问题

我有一个大文件要测试,它有很多依赖项,这些依赖项有它们自己的依赖项。因为上面提到的依赖关系,我想尽我所能去模仿。问题就在这里。如何模拟构造函数,使其包含属于它的方法

假设我正在测试类
Map
的方法
createMap

createMap
方法中,它使用

var layers = new Layers()
我在用电脑监视它

spyOn(window, 'Layers').and.callThrough()
这很好,但是稍后在
createMap
方法中,它调用了
layers.addLayer()
其中
addLayer
layers
类的方法。问题是,因为我模拟了
Layers
调用,所以它无法识别
addLayer
方法

有没有办法模拟它,使它包含被调用类的所有方法,或者是我唯一选择存根整个
类还是不模拟它

或者什么是处理这个问题的好方法?我试过
spyOn(Layers,'addLayer')
但它说找不到方法
addLayer


如果有点混乱,我很抱歉。我很难思考该如何提问。

我们来谈谈您提供的示例类

您正在为
Map
编写测试套件。必须模拟其所有依赖项(在示例中,我们只有
)。因为在单元测试中,您应该测试一层,尽可能小的功能。这意味着您应该提供这样一个模拟的
构造函数,它公开了
映射中使用的接口。例如:

function Layers() {
    this.addLayer = sinon.spy();
}

在此测试套件中,只有
Map
类应保持“真实”。也就是说,其代码不得更改。使用像
Layer
这样的实体模型,您可以确保不会触发与真实代码依赖项的任何交互(应该在不同的测试套件中测试自己编写的依赖项,还可以确保您不会尝试测试框架函数,如
$tate.resolve
$inject
等)。如果类
Map
复杂且具有多个依赖项,请调查有助于自动化此过程的sinon功能,例如IMO,无需监视
窗口,因为您可以通过创建具有相同名称的监视对象轻松地在本地范围内进行监视:

describe('Map', function () {
    var Layers;

    beforeEach(function () {
        Layers = function () {
            // alternatively, you could move this to Layers.prototype
            this.addLayers = jasmine.createSpy('Layers#addLayers');
        };
    });

    /* ... */
});

如果您想要自动模拟并使用CommonJS模块,您可以尝试框架,它是在Jasmine之上构建的。

使用依赖项注入或使用重新布线模块。@limelights您能解释一下关于重新布线模块的更多信息吗?这听起来像是一个愚蠢的后续问题,但如果我使用此方法,createMap方法不会调用
var layers=new layers()
它会失败,因为它是一个对象而不是一个函数/构造函数。@MikeJones你说得对,它需要是一个函数。请参阅更新的答案。