5

我正在使用 Backbone 和 Require.js。一切都很好,但是我想在我的应用程序中添加一些单元测试。我决定使用 Qunit.js。

在我的main.js文件中,我创建了新对象EventsView

require.config({
  paths: {
    jquery:                 'libs/jquery',
    underscore:             'libs/underscore',
    backbone:               'libs/backbone',
    qunit:                  'test/libs/qunit-1.10.0
    }
 });
 require(['view/eventsView', 
          'test/eventsView_test', 
          'test/eventView_test' ], function(EventsView){
           var events = new EventsView; //here I create first object my View
 });

eventsView.js initialize我呈现主视图

  define(['jquery',
          'backbone',
          'underscore',
          'collection/eventC',
          'model/eventM',
          'view/eventView'], function($, Backbone,_,EventC,EventM, EventView,){

 var EventsView = Backbone.View.extend({
    el: $(".contener"),     
    initialize: function(){
        this.render();
     },
     ....//other functions
    });
     return EventsView;
 });

所以现在我需要在其他文件eventsView_test.js中从这个视图调用函数。我不能这样做,因为视图将再次呈现:

  define(['jquery','qunit','view/eventsView'], function($,qunit,EventsView){
    //var eventsView = new EventsView(); // I can't create object here 

    test( "first_test_func", function() {
        var result = eventsView.first_test_func(2,2);
        equal( result, 4, "2 square equals 4" );
    });

我该怎么办?我需要某种单身人士或其他东西吗?

4

1 回答 1

2

很棒的问题,也是我一直看到的问题。

实际上,我通过创建我称之为“引导程序”的范式解决了这个问题,但你可以随意称呼它。关键是 Backbone 视图不会渲染自己,而是由谁使用它来负责。你会遇到 fetch() 之类的问题,所以幸运的是这也解决了这个问题。

目标:不要对渲染进行单元测试,而是一起跳过它!

你的视图变成了这样:

require(function () {
    var view = Backbone.View.extend({
        // initialize is executed on new, just as you found
        initialize: function (options) {
            _.bindAll(this);

            // Create models, initialize properties, and bind to events here.
            // Basically only do __UNEXPENSIVE__, non-dom-changing things that
            // you don't care get executed a lot.                

            this.someCollection = new Backbone.Collection();
            this.someCollection.on('add', this.onSomeCollectionAdd);
        },

        // bootstrap is for server-side operations that you don't want executed
        // by every single test.
        bootstrap: function () {
            this.someCollection.fetch().done(this.render);
        },

        render: function () {
            this.$el.html(...);
        },

        first_test_func: function () {

        }
    });

    return view;
});

这将如何在您的应用程序中使用:

require(['viewpath'], function (myView) {
    var instance = new myView({ el: $('#something') });
    instance.bootstrap(); //triggers fetch, or if no fetch needed, just render
});

现在可以毫无顾虑地进行单元测试。

define(['jquery','qunit','view/eventsView'], function($,qunit,EventsView){

    test( "first_test_func", function() {
        // Now this line won't call the server, or render.
        // You can isolate/test what you want.
        var eventsView = new EventsView();
        var result = eventsView.first_test_func(2,2);
        equal( result, 4, "2 square equals 4" );
    });
});

使用 SinonJS

我强烈建议查看SinonJS。对 JavaScript 进行单元测试,尤其是 Backbone 实现非常棒,因为它强大的模拟功能可以用来防止渲染和服务器调用(fetchsave等)实际访问服务器,同时仍然允许您断言它们被调用。

于 2013-02-09T01:58:45.893 回答