2014-01-15 49 views
3

當我不限制/去除測試通過的功能時。無法測試去抖動的主幹視圖事件

但是,當我爲了防止服務器氾濫而拒絕該事件時,測試不再通過。摩卡輸出AssertionError: expected execute to have been called at least once, but it was never called

需要注意的是,去抖通話在實時代碼中沒有錯誤。這就是爲什麼我徹底搞混測試失敗的原因。

測試:

describe('When information is entered into the search fields', function() { 
    it('vents up the search:for:churches command', function() { 
     var executeStub = sinon.stub(App, 'execute'); 

     view = new SearchForm() 
     view.render(); 

     view.$el.find('input[name=church_name]').val('baptist') 
     view.$el.find('input[name=zip]').val('61615') 

     view.$el.find('input[name=zip]').trigger($.Event('keypress')) 

     expect(executeStub).to.have.been.called 

     view.close(); 
     PEP.execute.restore() 
    }); 
}); 

無節流:

var SearchForm = Backbone.Marionette.ItemView.extend({ 

    template: 'search_form', 
    events: { 
     'keypress [data-search-field]' : 'searchForChurches' 
    }, 

    searchForChurches: function() { 
     console.log('not debounced') 
     var searchData = Backbone.Syphon.serialize(this); 
     App.execute("search:for:churches", searchData); 
    } 

}); 

經過調節:

var SearchForm = Backbone.Marionette.ItemView.extend({ 

    template: 'search_form', 
    events: { 
     'keypress [data-search-field]' : 'searchForChurches' 
    }, 

    searchForChurches: _.debounce(function() { 
     console.log('debounced') 
     var searchData = Backbone.Syphon.serialize(this); 
     App.execute("search:for:churches", searchData); 
    }, 200) 

}); 

編輯: 我也貼出了相關的後續問題:https://stackoverflow.com/questions/21167488/how-to-test-a-debounced-throttled-backbone-view-event-with-mocha-to-ensure-its-a

回答

5

西蒙的方法對大多數情況下工作很好,但我一直碰到不同的情況,導致更多的錯誤。花了更多時間閱讀sinon的文檔後,我認爲我有更好的方法。

Sinon的Fake Timers來救援。

describe('When information is entered into the search fields', function() { 
    it('vents up the search:for:churches command', function() { 
     var clock = sinon.useFakeTimers(); 
     var executeStub = sinon.stub(App, 'execute'); 

     view = new SearchForm() 
     view.render(); 

     view.$el.find('input[name=church_name]').val('baptist') 
     view.$el.find('input[name=zip]').val('61615') 

     view.$el.find('input[name=zip]').trigger($.Event('keypress')) 
     clock.tick(200) 

     expect(executeStub).to.have.been.called 

     view.close(); 
     PEP.execute.restore() 
     clock.restore()  
    }); 
}); 
1

節流什麼意思的執行將是異步的。這就是爲什麼它在你的測試中失敗的原因,因爲App.execute方法不是立即調用,所以當你聲明它已被調用時,它還沒有。

在這種情況下,請勿使用Sinon。只需手動存根你的方法:

describe('When information is entered into the search fields', function() { 
    it('vents up the search:for:churches command', function (done) { 
     var originalMethod = App.prototype.execute; 

     App.prototype.execute = function() { 
      App.prototype.execute = originalMethod; 
      done(); // calling done will pass the test, otherwise it'll fail with a timeout 
     }; 

     view = new SearchForm() 
     view.render(); 

     view.$el.find('input[name=church_name]').val('baptist') 
     view.$el.find('input[name=zip]').val('61615') 

     view.$el.find('input[name=zip]').trigger($.Event('keypress')) 

     view.close(); 
    }); 
}); 
8

使用UnderscoreJSSinonJS時,有一個問題。

  • UnderscoreJS去抖函數使用_.now
  • SinonJS覆蓋日期對象,但不包括_.now

出於測試目的,我在測試中的引導文件替換_.now

_.now = function() { 
    return new Date().getTime(); 
}; 
+0

這應該是公認的答案! – adrichman