2012-11-15 19 views
0

我正在爲我的Backbone views/models/collections編寫一些集成測試。當我在我的View上調用render時,它只是將模板呈現給它自己的el屬性,因此該html僅存儲在內存中而不是頁面上。下面是一個簡單的模型,並與結合在一個DOM元素的click事件的看法:當測試Backbone Views時在內存中的元素上觸發事件

var model = Backbone.Model.extend({ 
    urlRoot: '/api/model' 
}); 

var view = Backbone.View.extend({ 
    events: { 
     'click #remove': 'remove' 
    } 
    render: function() { 
     var html = _.template(this.template, this.model.toJSON()); 
     this.$el.html(html); 
    }, 
    remove: function() { 
     this.model.destroy(); 
    } 
}); 

我使用茉莉來寫我的測試。在下面的測試中,我想要做的就是窺探remove函數,看看它是否在點擊事件觸發元素#remove時被調用,該元素存在於傳遞給視圖的模板中。

// template 

<script id="tmpl"> 
    <input type="button" value="remove" id="remove"/> 
</script> 

// test 

describe('view', function() { 

    var view; 

    beforeEach(function() { 
     view = new view({ 
      template: $('#tmpl').html(), 
      model: new model() 
     }); 
    }); 

    it('should call remove when #remove click event fired', function() {  
     view.$('#remove').click(); 

     var ajax = mostRecentAjaxRequest(); 
     expect(ajax.url).toBe('/api/model'); 
     expect(ajax.method).toBe('DELETE'); 
    }); 

}); 

然而,由於#remove元素是在內存中,它實際上並沒有被添加到DOM,我不知道你將如何模擬點擊事件。事實上,我甚至不確定是否有可能?

這似乎有點奇怪想這樣做的測試,但我的測試,我想測試行爲而不是實施,這樣一來我不關心什麼之間發生的 - 我只想測試,如果用戶點擊#remove a DELETE請求被髮送回服務器。

+0

你確定的問題是,'從視圖remove'方法不會被調用?我創建了[demo](http://jsbin.com/ihabom/2/edit),我只在內存中調用'click',它按預期工作。你在瀏覽器環境或phantom.js中運行測試嗎? – dreame4

+0

FWIW,爲了測試對服務器的請求,我建議使用[sinon.js](http://sinonjs.org/docs/)來模擬它。它有一個你可以設置的假服務器。它應該比實際讓代碼在單元測試期間發送真正的AJAX請求更快(並且更安全?)。 –

+0

@DaveNichol它看起來像我使用[jasmine-ajax](https://github.com/pivotal/jasmine-ajax)去除ajax請求,所以沒有實際的請求正在進行。這就是'mostRecentAjaxRequest'調用的目的 – Gregg

回答

0

在我看來,你忘記了在click()之前的視圖上撥打render()。並且該模型需要有一個id或主幹不會真正嘗試對服務器進行刪除呼叫。我已經測試了很多觀點,就像之前沒有任何問題。

我剛剛對茉莉花2.0和茉莉花ajax 2.0進行了類似的測試。

現場代碼:

var MyModel = Backbone.Model.extend({ 
    urlRoot: '/api/model' 
}); 

var MyView = Backbone.View.extend({ 
    events: { 
    'click #remove': 'remove' 
    }, 
    initialize: function(options) { 
    this.template = options.template; 
    }, 
    render: function() { 
    var html = _.template(this.template, this.model.toJSON()); 
    this.$el.html(html); 
    }, 
    remove: function() { 
    this.model.destroy(); 
    } 
}); 

規格:

describe("testing", function() { 
    var view; 

    beforeEach(function() { 
    jasmine.Ajax.install(); 
    view = new MyView({ 
     template: '<input type="button" value="remove" id="remove"/>', 
     model: new MyModel({id: 123}) 
    }); 
    view.render(); 
    }); 

    it('should call remove when #remove click event fired', function() { 
    view.$('#remove').click(); 

    var ajax = jasmine.Ajax.requests.mostRecent(); 
    expect(ajax.url).toBe('/api/model/123'); 
    expect(ajax.method).toBe('DELETE'); 
    }); 
}); 
相關問題