fea*_*ool 12 javascript unit-testing node.js sinon
序言:我已经阅读了很多SO和博客文章,但没有看到任何回答这个特定问题的内容.也许我只是在寻找错误的东西......
假设我正在开发一个WidgetManager可以操作Widget对象的类.
如何使用sinon测试WidgetManager是否Widget正确使用API而不需要拉入整个Widget库?
基本原理:WidgetManager的测试应该与Widget类分离.也许我还没有编写Widget,或者Widget可能是一个外部库.无论哪种方式,我应该能够测试WidgetManager正确使用Widget的API而无需创建真实的Widgets.
我知道sinon模拟只能在现有的类上工作,据我所知,sinon存根也需要该类存在才能被存根.
为了使它具体化,我将如何测试Widget.create()在下面的代码中使用单个参数'name'调用一次?
// file: widget-manager.js
function WidgetManager() {
this.widgets = []
}
WidgetManager.prototype.addWidget = function(name) {
this.widgets.push(Widget.create(name));
}
Run Code Online (Sandbox Code Playgroud)
// file: widget-manager-test.js
var WidgetManager = require('../lib/widget-manager.js')
var sinon = require('sinon');
describe('WidgetManager', function() {
describe('#addWidget', function() {
it('should call Widget.create with the correct name', function() {
var widget_manager = new WidgetManager();
// what goes here?
});
it('should push one widget onto the widgets list', function() {
var widget_manager = new WidgetManager();
// what setup goes here?
widget_manager.addWidget('fred');
expect(widget_manager.widgets.length).to.equal(1);
});
});
Run Code Online (Sandbox Code Playgroud)
旁白:当然,我可以MockWidget使用适当的方法定义一个类进行测试,但我更感兴趣的是真正学习如何正确使用sinon的spy/stub/mock工具.
dun*_*all 10
答案实际上是依赖注入.
您希望测试以预期方式WidgetManager与依赖项(Widget)进行交互- 并且您希望自由地操纵和询问该依赖项.为此,您需要Widget在测试时注入存根版本.
根据WidgetManager创建方式,有几种依赖注入选项.
一个简单的方法是允许将Widget依赖项注入WidgetManager构造函数:
// file: widget-manager.js
function WidgetManager(Widget) {
this.Widget = Widget;
this.widgets = [];
}
WidgetManager.prototype.addWidget = function(name) {
this.widgets.push(this.Widget.create(name));
}
Run Code Online (Sandbox Code Playgroud)
然后在你的测试中,你只需将一个短线传递Widget到WidgetManager测试中:
it('should call Widget.create with the correct name', function() {
var stubbedWidget = {
create: sinon.stub()
}
var widget_manager = new WidgetManager(stubbedWidget);
widget_manager.addWidget('fred');
expect(stubbedWidget.create.calledOnce);
expect(stubbedWidget.create.args[0] === 'fred');
});
Run Code Online (Sandbox Code Playgroud)
您可以根据特定测试的需要修改存根的行为.例如,要测试创建窗口小部件后窗口小部件列表长度是否递增,您只需从存根create()方法返回一个对象:
var stubbedWidget = {
create: sinon.stub().returns({})
}
Run Code Online (Sandbox Code Playgroud)
这使您可以完全控制依赖关系,而无需模拟或存根所有方法,并允许您测试与其API的交互.
也有类似的选项proxyquire或重新连接这给在测试时间重写依赖更强大的选择.最合适的选择是实现和首选 - 但在所有情况下,您只是想在测试时替换给定的依赖项.
| 归档时间: |
|
| 查看次数: |
3896 次 |
| 最近记录: |