2013-04-25 41 views
3

我试图测试一个视图方法在我的模型触发事件时被调用。但这不起作用 - 而且我已经没有想到为什么会这样。下面是一个不正常的代码:触发Backbone模型事件不注册在我的Jasmine间谍

查看:

class View extends Backbone.View 
    initialize: -> 
    @.listenTo @model, 'request', @disableForm, @ 

    disableForm: -> 
    console.log 'disableForm' 

茉莉花测试:

describe "AJAX events", -> 

    it "when starting an AJAX request, disable the form", -> 
    model = new Backbone.Model() 
    view = new Backbone.View({ model: model }) 
    view.render() 

    spyOn(view, 'disableForm') 
    view.delegateEvents() 

    model.trigger 'request' 
    expect(view.disableForm).toHaveBeenCalled() 

此代码在浏览器的罚款。

另外 - console.log在我运行测试时打印出'disableForm' - 所以模型事件触发了disableForm的调用,但是我的间谍没有选择它(我的期望失败)。我试图把它放到waitsFor方法中,但他也没有什么区别。

任何想法我错了?

回答

8

问题是spyOn将用spy函数取代您的视图中的函数disableForm。但是此时模型被绑定到原始函数,因此替换视图中的函数对绑定到事件侦听器的函数没有影响。当你在模型上触发事件时,原始功能将被调用,而不是间谍。

+0

啊是的。这是完全合理的。谢谢。 – Joerg 2013-04-26 05:51:38

+0

测试模块中组件的推荐方法是什么?我可以在每次测试之前启动和停止模块,但这并不能模拟实际行为 – dbrin 2014-05-23 05:49:36

+0

我必须处理这个问题的方法是在测试中很好地和早期地监视原型方法。所以: spyOn(View.prototype,'disableForm'); 这确保了当你的方法被绑定时,它们绑定到方法的一个窥探版本。这不是很好,并导致稍微不太好的封装测试,但它的工作原理。 另一种方法是将绑定的实现更改为接受方法名称而不是函数引用。这样你可以在每个事件上按名称调用方法。但改变绑定实现有点沉重! – Tom 2014-06-13 14:18:51

0

可能是一个并发问题。不是使用集成测试,而是直接对disableForm方法进行单元测试,然后测试initialize进行正确绑定(或更好地使用Backbone.View.events哈希),可能会更容易。

此外,在您的测试中,对view.delegrateEvents()的呼叫似乎是不必要的。这是由于Backbone默认情况下在视图实例化时会调用delegateEvents,并且它只与events哈希交互,这似乎并未被使用。

+0

True - 这里的delegateEvents实际上没有区别,因为它只是指向事件散列。感谢那。 – Joerg 2013-04-26 05:53:04

0

上面的答案正确地阐明了为什么会发生这种情况:函数绑定在初始化上,间谍替换绑定后的函数,以便在事件触发时调用原始函数。

比在测试设置(在初始化之前)替换原型函数更麻烦的解决方案是将匿名函数绑定到事件并将视图的函数调用到它的内部。

@listenTo(model, event, => @viewFunction()) 

我不确定什么是性能权衡虽然。