testing - Prueba de unión del modelo en Backbone JS con Jasmine
backbone.js (5)
Tengo una vista que contiene un modelo. La vista escucha un evento del modelo y realizará una acción una vez que se desencadene el evento. A continuación está mi código
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
}
})
Quiero probar esto usando Jasmine y debajo está mi prueba (que no funciona)
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("[]");
})
¿Alguien sabe por qué la prueba anterior no funciona? El error que recibo es "Se esperaba que Spy showNotes se llamara con [''[]''] pero nunca se llamó".
Estás muy cerca;) spyOn
reemplaza la función con tu espía y te devuelve el espía. Entonces si lo haces:
var dialog_spy = spyOn(notes_dialog, "showNotes");
category.trigger("notesFetched", "[]");
expect(dialog_spy).toHaveBeenCalledWith("[]");
debería funcionar bien!
Estaba haciendo algo similar donde tenía una vista, pero no pude hacer que el espía funcionara correctamente a menos que lo añadiera al prototipo y antes de crear la instancia de la vista.
Esto es lo que finalmente funcionó para mí:
view.js
view = Backbone.View.extend({
initialize: function(){
this.collection.bind("change", this.onChange, this);
},
...
onChange: function(){
console.log("Called...");
}
});
jasmine_spec.js
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()
con la expectativa de toHaveBeenCalled()
y cambiaría a toHaveBeenCalledWith()
después de que funcione ...
Actualización 5/6/2013: update()
modificada update()
para set()
Intente modificar su código de prueba existente de la siguiente manera:
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("[]");
})
En su código original, la instancia del método al que llama es una definida en el cierre de enlace, mientras que la que está espiando está en la instancia de notes_dialog. Al mover el espía al prototipo, lo reemplaza antes de que se produzca el enlace, y por lo tanto, el cierre de enlace encapsula el espía, no el método original.
Su código se ve bien, excepto ¿tiene la prueba envuelta en una función de descripción, así como una función it?
describe("show notes", function(){
it("should show notes", function(){
// ... everything you already have here
});
});
Conjeturo total en este punto, pero ya que no estás mostrando la función de describir eso es todo lo que puedo pensar que sería. Debe tener un bloque de descripción para que las pruebas funcionen, si no tiene uno.
Usar un espía significa reemplazar la función que estás espiando. Entonces, en su caso, reemplaza la función de vinculación con el espía, por lo que la lógica interna del espía original ya no volverá a llamar. Y ese es el camino correcto porque no quieres probar que Backbones bind
es trabajo pero que has llamado bind
con los "notesFetched", this.showNotes, this
específicos "notesFetched", this.showNotes, this
.
Entonces, cómo probar esto. Como sabes, cada espía tiene el toHaveBeenCalledWith(arguments)
. En tu caso, debería verse así:
expect(category.bind).toHaveBeenCalledWith("notesFetched", category. showNotes, showNotes)
Entonces, ¿cómo probar que desencadenar el "notesfetched" en el modelo llamará a su función showNotes. Cada espía guarda todos los parámetros con los que fue llamado. Puede acceder al último con mostRecentCall.args
.
category.bind.mostRecentCall.args[1].call(category.bind.mostRecentCall.args[2], "[]");
expect(notes_dialog.showNotes).toHaveBeenCalledWith("[]");
mostRecentCall.args[1]
es el segundo argumento en su llamada de enlace ( this.showNotes
). mostRecentCall.args[2]
es el tercer argumento en su llamada de enlace ( this
).
Como tenemos la prueba de que bind
fue llamado con su método público showNotes
, también puede llamar directamente a su método público showNotes
, pero a veces los argumentos pasados pueden acceder desde afuera, por lo que usará la forma mostrada.