2013-04-25 45 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()) 

我不確定什麼是性能權衡雖然。