2013-05-05 4 views
5
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; 
         } 
        }); 
       } 
      } 
     } 

Wie Unit Test "save" Erfolg und Fehler Antworten in Jasmine zu testen?Wie Unit-Test die Backbone-Erfolg und Fehlerreaktion auf Speichern mit Jasmine

Antwort

1

Sie können Sinon.js verwenden, um einen gefälschten Server für Ihre Tests zu erstellen.

http://sinonjs.org/

Beispielcode:

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); 
    }); 

    }); 
0

Sie benötigen sinon Server-Antworten zu emulieren. Diese Bibliothek hat Dienstprogramme wie folgt aus:

this.server.respondWith("GET", "/episode/123", 
     [200, {"Content-Type": "application/json"}, 
     '{"id":123,"title":"Hollywood - Part 2"}']); 

Also, wenn Sie ein Modell mit der Wurzel Folge haben und ID 123, wird sinon diese Rückkehr auf einen Anruf holen.

dies lesen: http://tinnedfruit.com/2011/03/03/testing-backbone-apps-with-jasmine-sinon.html

aktualisieren: eine zweite Problemumgehung als Fragesteller Anfrage hinzufügen. Spott Methode speichern.

// Verwenden Sie diese in Ihren Tests statt Backbone.js Modell

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({ 
}); 

aber ich bin immer noch vorschlagen, dass Sie Sinon verwenden. Mocking der Backbone.js ist nicht elegant und unterstützt auch Header-Response-Codes und andere Sachen ist auch komplexer und eine Art neu erfinden das Rad. Während mit Sinon müssen Sie nur die Bibliothek hinzufügen eine Serverantwort erstellen.

+0

ich verwende die folgende Technologien backbone.js, require.js, jquery, Restdienste über WebAPI. Von Jasmin verspotte ich das Modellobjekt und verbinde es mit einer Ansicht für Unit-Tests. wenn ich die Antwort von der Ansicht auf das Scheinmodell erhalte, wie man die Save (Erfolg, Fehler) -Antworten des Modells einteilt. Gibt es keine Möglichkeit, die Modellantworten ohne Sinon zu testen? – Gururaj

+0

Sinon ist nur andere JavaScript-Bibliothek, nicht sicher, warum Sie es nicht hinzufügen können. Eine andere Möglichkeit besteht jedoch darin, die Speichermethode zu überschreiben. Ich werde diese Problemumgehung in meiner Antwort hinzufügen. –

2

Um dies ohne einen gefälschten Server zu testen, können Sie testen, ob die Funktion an das Modell gebunden wurde und dann die binded-Funktion selbst aufrufen. Mit anderen Worten, verspotten Sie den Ajax-Save-Part aus dem Modell.

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() 
0

Ich bin nicht sicher, ich durch sinon gehe gerne hier, afterall die Ajax-Aufruf von Backbone gemacht wird, nicht durch das Gerät, das Sie testen, hier ist meine Lösung

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(); 
    });