我有一个包含模型的视图。视图从模型中侦听事件,并在触发事件后执行操作。以下是我的代码
window.Category = Backbone.Model.extend({})
window.notesDialog = Backbone.View.extend({
initialize: function() {
this.model.bind("notesFetched", this.showNotes, this);
},
showNotes: function(notes) {
//do stuffs here
}
})
我想使用Jasmine进行测试,下面是我的测试(不起作用)
it("should show notes", function() {
var category = new Category;
var notes_dialog = new NotesDialog({model: category})
spyOn(notes_dialog, "showNotes");
category.trigger("notesFetched", "[]");
expect(notes_dialog.showNotes).toHaveBeenCalledWith("[]");
})
有谁知道为什么上述测试不起作用?我得到的错误是“预期的间谍showNotes被调用了['[]']但它从未被调用过。”
答案 0 :(得分:7)
我在做一个类似的地方,但是我没有让间谍正常工作,除非我把它添加到原型中,然后才创建视图实例。
这最终对我有用:
view = Backbone.View.extend({
initialize: function(){
this.collection.bind("change", this.onChange, this);
},
...
onChange: function(){
console.log("Called...");
}
});
describe("Test Event", function(){
it("Should spy on change event", function(){
var spy = spyOn(view.prototype, 'onChange').andCallThrough()
var v = new view( {collection: some_collection });
// Trigger the change event
some_collection.set();
expect(spy).toHaveBeenCalled()
});
});
我最初会考虑toHaveBeenCalled()
期望,并在您完成工作后更改为toHaveBeenCalledWith()
...
2013年5月6日更新:将update()
更改为set()
答案 1 :(得分:3)
尝试按如下方式修改现有测试代码:
it("should show notes", function() {
var category = new Category;
spyOn(NotesDialog.prototype, "showNotes");
var notes_dialog = new NotesDialog({model: category})
category.trigger("notesFetched", "[]");
expect(notes_dialog.showNotes).toHaveBeenCalledWith("[]");
})
在原始代码中,您调用的方法的实例是在绑定闭包中定义的实例,而您正在监视的实例是在notes_dialog实例中。通过将间谍移动到原型,您将在绑定发生之前替换它,因此绑定闭包封装了间谍,而不是原始方法。
答案 2 :(得分:1)
使用间谍手段替换你监视的功能。因此,在您的情况下,您将使用spy替换bind函数,因此原始间谍的内部逻辑将不再调用。这就是正确的方法,因为你不想测试Backbones bind
是否正常工作,但是您已使用特定的参数bind
调用了"notesFetched", this.showNotes, this
。
那么如何测试呢。如你所知,每个间谍都有toHaveBeenCalledWith(arguments)
方法。在你的情况下它应该是这样的:
expect(category.bind).toHaveBeenCalledWith("notesFetched", category. showNotes, showNotes)
那么如何测试触发器模型上的“notesFetched”将调用你的showNotes函数。
每个间谍都会保存他所调用的所有参数。您可以使用mostRecentCall.args
访问最后一个。
category.bind.mostRecentCall.args[1].call(category.bind.mostRecentCall.args[2], "[]");
expect(notes_dialog.showNotes).toHaveBeenCalledWith("[]");
mostRecentCall.args[1]
是绑定调用中的第二个参数(this.showNotes
)。 mostRecentCall.args[2]
是绑定调用中的第三个参数(this
)。
由于我们测试了使用您的公共方法bind
调用showNotes
,您还可以直接调用您的公共方法showNotes
,但有时传递的参数可以从外部访问你将使用所示的方式。
答案 3 :(得分:0)
您的代码看起来很好,除了您是否将测试包装在describe函数中,以及它的功能?
describe("show notes", function(){
it("should show notes", function(){
// ... everything you already have here
});
});
此时的总猜测,但由于你没有显示描述功能,我认为这就是全部。如果你没有测试,你必须有一个描述块才能使测试工作。
答案 4 :(得分:-1)
你非常接近;)
spyOn
用你的间谍取代这个功能,然后给你留下间谍。
所以如果你这样做:
var dialog_spy = spyOn(notes_dialog, "showNotes");
category.trigger("notesFetched", "[]");
expect(dialog_spy).toHaveBeenCalledWith("[]");
应该工作得很好!