onSaveEvent: function (event) {
if (this.model !== null) {
var that = this;
this.model.save(this.model.toJSON(), {
success: function (model) {
that.model = model;
that.model.attributes.isDirty = false;
},
error: function (model, xhr) {
that.model.attributes.isDirty = true;
}
});
}
}
}
如何在Jasmine中对模型的成功和错误响应进行单元测试?
答案 0 :(得分:2)
要在没有虚假服务器的情况下测试此功能,您可以测试该功能是否绑定到模型,然后自行调用绑定功能。换句话说,模拟出模型中的ajax保存部分。
var view = new YourView()
jasmine.spyOne(view.model, 'save')
view. onSaveEvent()
var args = view.model.save.mostRecentCall.args
args[1].success()
expect(view.model.attributes.isDirty).toBeFalsy()
args[1].error()
expect(view.model.attributes.isDirty). toBeTruthy()
答案 1 :(得分:1)
您可以使用Sinon.js为您的测试创建虚假服务器。
示例代码:
describe("when saving a user model", function() {
beforeEach(function() {
this.server = sinon.fakeServer.create();
this.responseBody = '{"name":"test user","id":1,"title":"tester"}';
this.server.respondWith(
"POST",
"/user",
[
200,
{"Content-Type": "application/json"},
this.responseBody
]
);
this.eventSpy = sinon.spy();
});
afterEach(function() {
this.server.restore();
});
it("should not save when name is blank", function() {
this.user.bind("error", this.eventSpy);
this.user.save({"name": ""});
expect(this.eventSpy).toHaveBeenCalledOnce();
expect(this.eventSpy).toHaveBeenCalledWith(this.user, "cannot have a blank name");
});
it("should call the server", function() {
this.user.save();
expect(this.server.requests[0].method).toEqual("POST");
expect(this.server.requests[0].url).toEqual("/user");
expect(JSON.parse(this.server.requests[0].requestBody)).toEqual(this.user.attributes);
});
});
答案 2 :(得分:0)
您需要sinon来模拟服务器响应。这个库有这样的实用程序:
this.server.respondWith("GET", "/episode/123",
[200, {"Content-Type": "application/json"},
'{"id":123,"title":"Hollywood - Part 2"}']);
因此,只要你有一个带有根剧集和id 123的模型,sinon就会在提取调用中返回它。
阅读本文: http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html
更新:添加第二个解决方法作为提问者请求。模拟保存方法。
//在测试中使用它而不是Backbone.js模型
var ExtendedModel = Backbone.Model.extend({
//mocked save:
save : function(data, options){
if( data ){
this.set(data);
}
var mocked = this.toJSON();
if( !mocked.id ){
mocked.id = new Date().getTime();
}
mocked = this.parse(mocked);
if( options.success ){
options.success(this);
}
if( options.error ){
options.error(this);
}
}
});
var MyModel = ExtendedModel.extend({
});
但是我仍然建议你使用Sinon。模拟Backbone.js并不优雅,也支持标题响应代码和其他东西也更复杂,并重新发明轮子。使用sinon时,您只需要为库添加一个创建服务器响应。
答案 3 :(得分:0)
我不确定我是否喜欢在这里经历sinon,毕竟ajax调用是由骨干进行的,而不是你正在测试的单位,这是我的解决方案
var Model = Backbone.Model.extend({
success_callback : function (model){
this.model = model;
this.model.attributes.isDirty = false;
},
error_callback: function (model, xhr){
},
onSaveEvent: function (event) {
this.save([], {
success: _.bind(this.save_success, this),
error: _.bind(this.error_callback, this);
});
});
var callback_invoker = function(type_str, which_argument) {
this.which_argument = which_argument || 0;
this.type_str = type_str;
var func = function() {
var options = arguments[this.which_argument] || {};
if (this.type_str == 'success') {
var run = options.success || function() {};
}else if (this.type_str == 'error') {
var run = options.error || function() {};
}
run();
};
this.function = _.bind(func, this);
};
it('save success calls callback', function() {
instance = new Model();
spyOn(instance, 'save_success');
spyOn(_,'bind').andCallThrough();
var invoker = new callback_invoker('success', 1);
spyOn(instance, 'save').andCallFake(invoker.function);
instance.onSaveEvent();
expect(_.bind).toHaveBeenCalledWith(instance.save_success, instance);
expect(instance.save_success).toHaveBeenCalled();
});