[英]Unit testing with Jasmine, mocking a constructor
I'm unit testing JavaScript with Jasmine and I am running into some problems.我正在使用 Jasmine 对 JavaScript 进行单元测试,但遇到了一些问题。
I have a large file to test and it has a lot of dependencies and those dependencies have their own dependencies.我有一个大文件要测试,它有很多依赖项,这些依赖项有自己的依赖项。 Because of said dependencies I want to mock all I can.
由于上述依赖关系,我想尽我所能模拟。 There lies the problem.
这就是问题所在。 How can I mock a constructor so that it includes the methods that belong to it?
如何模拟构造函数以使其包含属于它的方法?
Lets say I'm testing a method
createMap<\/code> of class
Map<\/code> :
假设我正在测试类
Map<\/code>的方法
createMap<\/code> :
In that
createMap<\/code> method it calls for
Layers<\/code> class constructor using
在该
createMap<\/code>方法中,它使用调用
Layers<\/code>类构造函数
var layers = new Layers()
IMO, it's unnecessary to spy on window
, since you can easily shadow the variable in local scope by creating a spy object with the same name: IMO,没有必要监视
window
,因为您可以通过创建具有相同名称的间谍对象轻松地在本地范围内隐藏变量 :
describe('Map', function () {
var Layers;
beforeEach(function () {
Layers = function () {
// alternatively, you could move this to Layers.prototype
this.addLayers = jasmine.createSpy('Layers#addLayers');
};
});
/* ... */
});
If you want an automatic mocking and using CommonJS modules, you may try Jest framework, which is built on top of Jasmine. 如果你想要一个自动模拟和使用CommonJS模块,你可以尝试Jest框架,它建立在Jasmine之上。
Let's talk in terms of example classes you have provided. 让我们谈谈您提供的示例类。
You're writing a test suite for Map
. 您正在为
Map
编写测试套件。 All its dependencies (in example we have only Layer
) MUST be mocked. 它的所有依赖项(例如我们只有
Layer
)必须被模拟。 Because in a unit test you're supposed to test one layer, as small functionality as possible. 因为在单元测试中,您应该测试一个层,尽可能小的功能。 It means that you should provide such a mocked
Layer
constructor that exposes interface used in Map
. 这意味着您应该提供这样一个模拟的
Layer
构造函数,该构造函数公开Map
使用的接口。 For example: 例如:
function Layers() {
this.addLayer = sinon.spy();
}
In this test suite only Map
class should remain "real". 在这个测试套件中,只有
Map
类应该保持“真实”。 Ie it's code must not be altered. 即它的代码不得更改。 And with such mockups like
Layer
you make sure that you do not trigger any interaction with real-code dependencies (own-written dependencies should be tested in a different test suite, also make sure you don't try to test framework functions, like $tate.resolve
, $inject
etc.). 使用像
Layer
这样的模型,你可以确保不会触发与实际代码依赖的任何交互(自己编写的依赖项应该在不同的测试套件中进行测试,同时确保你不要尝试测试框架函数,比如$tate.resolve
, $inject
等)。 If class Map
is complicated and has multiple dependencies, investigate sinon features that help automate this process, for example sinon.mock
如果类
Map
很复杂且具有多个依赖关系,请调查有助于自动执行此过程的sinon功能,例如sinon.mock
If you ever transpile class syntax to a es3 or another pre-2015 dialect you will discover something interesting.如果您曾经将类语法转换为 es3 或其他 2015 年之前的方言,您会发现一些有趣的东西。
class a {
constructor(){
...
}
index()
{
...
}
}
Becomes:变成:
var a = /** @class */ (function () {
function a() {
...
}
a.prototype.index = function () {
...
};
return a;
}());
This same implementation is used by later standards but masked by the 2015 class syntax.稍后的标准使用相同的实现,但被 2015 类语法掩盖。 In other words
a.index
doesn't exist instead it's defined as a.prototype.index
.换句话说,
a.index
不存在,而是被定义为a.prototype.index
。 Thus you need spyOn(a.prototype, 'index')
to spy on it.因此,您需要
spyOn(a.prototype, 'index')
来监视它。
Change spyOn(Layers, 'addLayer')
to spyOn(Layers.prototype, 'addLayer')
spyOn(Layers, 'addLayer')
更改为spyOn(Layers.prototype, 'addLayer')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.