我有一个骨干视图,我想创建一个测试来确认某个元素上的click事件会调用绑定到该元素的函数。 我的观点是:
PromptView = Backbone.View.extend({
id:"promptPage",
attributes:{
"data-role":"page",
"data-theme":"a"
},
events:{
"click #btnYes": "answerYes",
"tap #btnYes": "answerYes"
},
render: function(){
$(this.el).html(_.template($('#promptPage-template').html(), this.model.toJSON()));
return this;
},
answerYes: function(){
alert('yes');
}
});
我的规格是:
beforeEach(function() {
model = new PromptModel;
view = new PromptView({model:model});
loadFixtures('promptPage.tmpl');
});
it("should be able to answer a question with yes", function() {
var button = $("#btnYes", view.render().el);
expect(button.length).toBe(1);
spyOn(view, 'answerYes');
button.click();
expect(view.answerYes).toHaveBeenCalled();
});
但是上面的视图定义在原型 proto 上创建了answerYes方法,但是间谍在视图中的实际实例上创建了一个函数,所以我最终得到了一个view.answerYes()是间谍和观点.__ proto __。answerYes,这是我真正想要窥探的那个。
如何创建一个间谍,以便它覆盖视图定义的answerYes方法?
答案 0 :(得分:54)
嗨,我今天遇到了同样的问题。我刚刚找到解决方案,在创建spyed方法(answerYes)后,你必须刷新视图的事件来调用新的spyed方法;):
[...] spyOn(view, 'answerYes'); view.delegateEvents(); button.click(); expect(view.answerYes).toHaveBeenCalled(); [...]
More information about delegate events
玩得开心!
答案 1 :(得分:3)
我通常喜欢假设框架代码已经完成它应该做的事情,并且只测试我对它的使用,所以我发现测试验证事件哈希是可以接受的。如果我发现自己重复骨干功能以便测试我的东西(比如委托事件),那么也许我离集成测试更近了一步,而不是我真正需要的。我也大量使用原型,以便在我的单元测试中成为超级孤立的女士。当然,拥有一个可以完成所有练习的集成层仍然很重要,但我发现反馈循环对于测试驱动阶段来说太长了。
答案 2 :(得分:3)
这会在answerYes
的{{1}}方法上创建间谍:
PromptView
答案 3 :(得分:1)
TL; DR:窥探实例方法,而不是原型。
我认为你需要以不同方式设置你的测试。在it
块中存在太多关注点和太多期望,并且您还在污染全局命名空间,这可能导致测试问题。
beforeEach(function() {
loadFixtures('promptPage.tmpl');
var model = new PromptModel();
this.view = new PromptView({model:model});
this.view.render();
this.button = this.view.$("#btnYes");
});
it("should render the button", function(){
expect(this.button.length).toBe(1);
});
it("should be able to answer a question with yes", function() {
spyOn(this.view, 'answerYes');
this.button.click();
expect(this.view.answerYes).toHaveBeenCalled();
});
按钮的长度并不严格要求。如果按钮没有长度(未找到),则会出现其他故障。但是你可能希望它更容易弄清楚视图没有正确呈现。
你也应该像你一直在监视view
实例。 PromptView
的定义确实在原型中添加了answerYes
方法,是的,但是您要监视的方法是视图实例,而不是原型。
如果您监视原型的方法,那么每次尝试在测试中使用此视图时,answerYes
方法将是间谍,而不是实际方法。这可能听起来不错,但它会导致问题,因为当您多次调用此方法时,您将无法访问有效的间谍数据。它只会累积对那个间谍的所有调用。如果你试图对原型方法进行两次侦察,你最终可能会遇到一个间谍间谍,这可能是一件奇怪的事情,可能会引发问题。
答案 4 :(得分:0)
If you have trouble using spyOn, you could consider creating a spy. So something like:
var eventSpy;
eventSpy = jasmine.createSpy('eventSpy');
view.$el.on('myCustom:event', eventSpy);