9

在监视骨干路由器上的方法调用时遇到问题,以确保它在给定路由上调用正确的方法。

测试摘录

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

路由器

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

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

除了最后一个测试“应该调用索引”之外,一切都通过了。它失败并显示消息“预期的间谍索引已被调用”。我试过其他变种

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

我还可以在原始 Router.index 函数的测试输出中看到“router.index 已被调用”日志输出

谢谢!

编辑:一种解决方案

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

2 回答 2

15

我花了太多时间来提供一个有效的 jsFiddle,@MarkRushakoff 已经回答了这个问题。

我还是有一些意见。

Backbone 绑定路由的方式使得测试它变得非常困难。

关键是路由器方法不是直接在路由器实例中调用的,方法是作为回调存储在内部Backbone.history.route等待执行的,检查Backbone.Router.route代码

此操作是在Router实例化的那一刻完成的,因此您必须在实例化引用之前使用Router.methodspy ,因此您还必须在激活后延迟。Backbone.history.startspy

由于您必须在spy创建路由器实例之前声明,您必须在Class级别进行。

这么说这是我带来的最简单的解决方案:

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

结论,我认为Backbone.Router实现没有直观的设计。

于 2012-08-07T15:38:15.827 回答
4

我很确定这与 Backbone 在使用路由哈希时绑定到其路由方法的方式有关(尤其是在您看到控制台日志正确输出的情况下)。也就是说,路由器已绑定到原始index方法,但您的间谍已替换“当前”index方法。

你有两个选择:

  • spyOn(@router, "index")在路由器绑定到路由之前(可能很难)
  • 窥探原型的index方法:spyOn(App.router.prototype, "index"); @router.navigate('', true); expect(App.router.prototype.index).toHaveBeenCalled();
于 2012-08-07T14:09:07.413 回答