【发布时间】:2012-11-15 09:56:32
【问题描述】:
我正在为我的 Backbone 视图/模型/集合编写一些集成测试。当我在我的View 上调用render 时,它只是将一个模板呈现给它自己的el 属性,因此html 只是存储在内存中而不是页面上。下面是一个简单的模型,以及一个带有绑定到 DOM 元素的点击事件的视图:
var model = Backbone.Model.extend({
urlRoot: '/api/model'
});
var view = Backbone.View.extend({
events: {
'click #remove': 'remove'
}
render: function () {
var html = _.template(this.template, this.model.toJSON());
this.$el.html(html);
},
remove: function () {
this.model.destroy();
}
});
我正在使用 Jasmine 编写测试。在下面的测试中,我要做的就是监视remove 函数,看看当我传递给视图的模板中存在的元素#remove 触发点击事件时是否调用它。
// template
<script id="tmpl">
<input type="button" value="remove" id="remove"/>
</script>
// test
describe('view', function () {
var view;
beforeEach(function () {
view = new view({
template: $('#tmpl').html(),
model: new model()
});
});
it('should call remove when #remove click event fired', function () {
view.$('#remove').click();
var ajax = mostRecentAjaxRequest();
expect(ajax.url).toBe('/api/model');
expect(ajax.method).toBe('DELETE');
});
});
但是,由于 #remove 元素在内存中,并且实际上并未添加到 DOM 中,因此我不确定您将如何模拟单击事件。事实上我什至不确定这是否可能?
想要在测试中执行此操作似乎有点奇怪,但在我的测试中,我试图测试行为而不是实现,这样我不在乎两者之间发生了什么——我只是想测试一下,如果用户点击#remove,DELETE 请求会被发送回服务器。
【问题讨论】:
-
您确定问题是视图中的
remove方法没有被调用吗?我创建了demo,我在一个仅在内存中的元素上调用click,它按预期工作。您是在浏览器环境中还是在 phantom.js 中运行测试? -
FWIW,为了测试对服务器的请求,我建议使用 sinon.js 来模拟它。它有一个你可以设置的假服务器。它应该比在单元测试期间实际让您的代码发送真正的 AJAX 请求更快(更安全?)。
-
@DaveNichol 在我看来他正在使用jasmine-ajax 来存根 ajax 请求,因此没有发出实际请求。这就是
mostRecentAjaxRequest调用的目的
标签: javascript backbone.js integration-testing jasmine