2012-08-07 26 views
9

Problemas al espiar las llamadas al método en un enrutador de red troncal para garantizar que el método sea el correcto en una ruta determinada.Espiando las llamadas a la ruta Backbone.js con Jasmine

extracto de la prueba

describe 'Router', -> 
    beforeEach -> 
     @router = new App.Router() 
     Backbone.history.start() 

    afterEach -> 
     Backbone.history.stop() 

    describe 'routes', -> 
     it 'should be defined', -> 
       expect(@router.routes).toBeDefined() 

     describe 'default route', -> 
      it 'should be defined', -> 
        expect(@router.routes['']).toBeDefined() 

      it 'should call index', -> 
       spy = spyOn(@router, "index") 
       @router.navigate('', true) 
       expect(spy).toHaveBeenCalled() 

El router

class App.Router extends Backbone.Router 
    routes: 
     '' : 'index' 

    index: -> 
     console.log "router.index has been called" 

Todo pasa, excepto la última prueba "debe llamar índice". Falla con el mensaje "Se ha llamado el índice de espionaje esperado". He intentado otras variantes

it "should call index", -> 
    spyOn(@router, "index") 
    @router.navigate('', true) 
    expect(@router.index).toHaveBeenCalled() 

también puedo ver el "router.index se ha llamado" la salida del registro en la salida de prueba de la función original Router.index

Gracias!

EDIT: Una solución

describe '#1 Solution', -> 
    it 'should call index', -> 
     spyOn(App.Router.prototype, "index") 
     @router = new App.Router() 
     Backbone.history.start() 
     @router.navigate('', true) 
     expect(App.Router.prototype.index).toHaveBeenCalled() 

Respuesta

15

Se ha tomado una sobredosis mucho tiempo para mí para venir con un working jsFiddle y la pregunta ya ha sido respondida por @MarkRushakoff.

Todavía tengo algunos comentarios.

La forma en que Backbone une las rutas hace que sea muy difícil probarla.

El punto es que el router métodos no son llamados directamente en la instancia enrutador , los métodos taked como devoluciones de llamada y se almacenan en una interna Backbone.history.route espera de ejecución, check the Backbone.Router.route code.

Esta operación se realiza en el momento en que el Router es instantiate, por lo que tiene a su spyRouter.method antes de crear instancias de la referencia, por lo que para usted tiene que retrasar Backbone.history.start también después de la spy se ha activado.

Como tiene que declarar el spy antes de que se cree la instancia del enrutador, debe hacerlo en un nivel clase.

Said por lo que esta es la solución más simple Vine con:

describe("Router", function() { 
    afterEach(function(){ 
    Backbone.history.stop(); 
    }); 

    it("should call index", function(){ 
    spyOn(App.Router.prototype, "index") 
    var router = new App.Router(); // instance created after spy activation 
    Backbone.history.start();  // it has to start after the Router instance is created 

    router.navigate('', true); 

    expect(App.Router.prototype.index).toHaveBeenCalled(); 
    }); 
}); 

Conclusión, creo que la aplicación Backbone.Router no tiene un diseño intuitivo.

+1

¡Gracias! Parece que es el camino a seguir :) – eldewall

+0

Esta no es una forma viable de probar la activación de una ruta. Todo lo que se está probando es que la función de índice estaba vinculada al enrutador como una devolución de llamada, no que la función realmente se llama cuando se desencadenó la ruta. Ver [este S.O. post] (http://stackoverflow.com/questions/9215737/testing-routers-in-backbone-js-properly) para saber cómo se llamó a la función de ruta correspondiente cuando un enrutador coincide con una url. – louism2

4

Estoy bastante seguro de que esto tiene que ver con la forma en que la espina dorsal se une a sus métodos de enrutamiento cuando se utiliza un hash rutas (especialmente si estás viendo una consola log correctamente la salida). Es decir, el enrutador se ha vinculado al método original index, pero su espía ha reemplazado el método "actual" index.

tiene dos opciones:

  • spyOn(@router, "index") antes de que el router se une a las rutas (puede ser difícil)
  • espía en index método del prototipo: spyOn(App.router.prototype, "index"); @router.navigate('', true); expect(App.router.prototype.index).toHaveBeenCalled();
+0

Gracias, eso funciona :) La opción número dos es viable. El espía debe agregarse antes de que se realice una nueva instancia del enrutador. ¡Supongo que eso está bien! – eldewall

+0

Opción uno, creo que no es posible debido a que _routes binding_ se realiza en _initialize_, por lo que en el momento en que tiene una referencia a la instancia, la vinculación ya se ha realizado. – fguillen

Cuestiones relacionadas