测试Backbone Views时触发内存中元素的事件

时间:2012-11-15 09:56:33

标签: javascript backbone.js integration-testing jasmine

我正在为我的Backbone视图/模型/集合编写一些集成测试。当我在render上调用View时,它只是将模板呈现给它自己的el属性,因此html只是存储在内存中而不是存储在页面上。下面是一个简单的模型,以及一个绑定到DOM元素的click事件的视图:

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();
    }
});

我正在使用Jasmine编写测试。在下面的测试中,我想做的就是监视remove函数,看看当我为传递给视图的模板中出现的元素#remove触发click事件时是否调用它

// 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中,我不确定如何模拟click事件。事实上,我甚至不确定它是否可能?

在测试中想要这样做似乎有点奇怪,但是我的测试我试图测试行为而不是实现,这样我不关心中间发生的事情 - 我只想测试一下,如果用户点击#removeDELETE请求会被发送回服务器。

1 个答案:

答案 0 :(得分:0)

在我看来,您忘了在render()按钮之前在视图上致电click()。并且模型需要id或者主干不会实际尝试对服务器进行删除调用。我之前已经测试了大量的观点而没有任何问题。

我刚刚针对jasmine 2.0和jasmine-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');
  });
});