¿Por qué no se llama a este espía sinon cuando realizo esta testing?

Tengo un model de Backbone:

class DateTimeSelector extends Backbone.Model initialize: -> @bind 'change:date', @updateDatetime @bind 'change:time', @updateDatetime updateDatetime: => # do some stuff with the sate and time 

Y tengo algunas testings para ese código usando jasmin y sinon.js

 describe "DateTimeSelector", -> beforeEach -> @datetime = new DateTimeSelector() describe "updateDatetime", -> beforeEach -> @updateSpy = sinon.spy(@datetime, 'updateDatetime') afterEach -> @datetime.updateDatetime.restre() # passes it "should be called when we call it", -> @datetime.updateDatetime() expect(@updateSpy).toHaveBeenCalledOnce() # fails it "should be called when we trigger it", -> @datetime.trigger 'change:date' expect(@updateSpy).toHaveBeenCalled() # fails it "should be called when we set the date", -> @datetime.set { date: new Date() } expect(@updateSpy).toHaveBeenCalled() 

Parece que funciona cuando lo uso en el browser pero parece que no puedo pasar las testings. ¿Alguien puede iluminarme?

duckyfuzz, está experimentando este problema porque cuando está creando el espía (que en realidad ajusta la function original y crea un nivel de indirección para insert sus services de invocación del método de seguimiento), la vinculación de los events ya se ha realizado. Lo que significa que aunque el espía envolvió la function original, el enlace del evento hace reference a la function original y no al espía envuelto. Por lo tanto, cuando testing, la function original se ejecuta en el desencadenador de events, pero el seguimiento de espías está en un nivel superior y no se ejecuta.

Para asegurarse de que el enlace del evento apunta realmente a la function de espionaje envuelto, debe crear el espía antes de crear el object model (lo mismo ocurre si está probando vistas). Para hacer eso crea el espía en el prototipo. "Método" de la class:

en la sección beforeEach -> before @datetime = new DateTimeSelector () crea el espía: @updateSpy = sinon.spy ( DateTimeSelector.prototype , 'updateDatetime')

asegúrate de cambiar tu sección afterEach -> donde devuelves el prototipo a la normalidad, así: @ updateSpy.restre ()

este debería ser tu código:

 describe "DateTimeSelector", -> beforeEach -> @updateSpy = sinon.spy(DateTimeSelector.prototype, 'updateDatetime') @datetime = new DateTimeSelector() afterEach -> @updateSpy.restre() # passes it "should be called when we call it", -> @datetime.updateDatetime() expect(@updateSpy).toHaveBeenCalledOnce() # should pass now it "should be called when we trigger it", -> @datetime.trigger 'change:date' expect(@updateSpy).toHaveBeenCalled() # should pass now it "should be called when we set the date", -> @datetime.set { date: new Date() } expect(@updateSpy).toHaveBeenCalled() 

Por cierto, si usas el plugin jasmin-sinon.js entonces tu syntax está bien

Estás mezclando la syntax burlona de jasmine y sinón juntos.

En su testing de aprobación, su espía de sinon expone la propiedad calledOnce pero está usando una function de jasmine para toHaveBeenCalledOnce() . Esta function no existe en el espía de sinón, por lo que esencialmente no está teniendo lugar ninguna afirmación.

En las testings toHaveBeenCalled() , toHaveBeenCalled() function de espionaje de jasmine a toHaveBeenCalled() en tu espía de sinón. Jasmine tiene su propia syntax para crear un espía: spyOn(obj, 'method');