在Backbone Router上监视方法调用时遇到问题,以确保它在给定路由上调用正确的方法。
摘自测试
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()
答案 0 :(得分:15)
我花了太多时间来working jsFiddle并且@MarkRushakoff已经回答了这个问题。
我还有一些意见。
Backbone绑定路由的方式非常难以测试。
重点是路由器方法不是直接在路由器实例中调用,这些方法被作为回调进行存储并存储在内部Backbone.history.route
等待执行,check the Backbone.Router.route code。
此操作在Router
实例化时完成,因此在实例化引用之前必须spy
Router.method ,因此您必须在Backbone.history.start
被激活后也会延迟spy
。
由于您必须在创建路由器实例之前声明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
实现没有直观的设计。
答案 1 :(得分:4)
我很确定这与使用路由哈希时Backbone绑定到路由方法的方式有关(特别是如果您看到控制台日志正确输出)。也就是说,路由器已绑定到原始index
方法,但您的间谍已替换“当前”index
方法。
您有两种选择:
spyOn(@router, "index")
(可能很难)index
方法:spyOn(App.router.prototype, "index"); @router.navigate('', true); expect(App.router.prototype.index).toHaveBeenCalled();