【问题标题】:Triggering event on an element in memory when testing Backbone Views测试主干视图时在内存中的元素上触发事件
【发布时间】:2012-11-15 09:56:32
【问题描述】:

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

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 触发点击事件时是否调用它。

// 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 中,因此我不确定您将如何模拟单击事件。事实上我什至不确定这是否可能?

想要在测试中执行此操作似乎有点奇怪,但在我的测试中,我试图测试行为而不是实现,这样我不在乎两者之间发生了什么——我只是想测试一下,如果用户点击#removeDELETE 请求会被发送回服务器。

【问题讨论】:

  • 您确定问题是视图中的remove 方法没有被调用吗?我创建了demo,我在一个仅在内存中的元素上调用click,它按预期工作。您是在浏览器环境中还是在 phantom.js 中运行测试?
  • FWIW,为了测试对服务器的请求,我建议使用 sinon.js 来模拟它。它有一个你可以设置的假服务器。它应该比在单元测试期间实际让您的代码发送真正的 AJAX 请求更快(更安全?)。
  • @DaveNichol 在我看来他正在使用jasmine-ajax 来存根 ajax 请求,因此没有发出实际请求。这就是mostRecentAjaxRequest 调用的目的

标签: javascript backbone.js integration-testing jasmine


【解决方案1】:

在我看来,您在click() 按钮之前忘记在视图上调用render()。并且模型需要有一个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');
  });
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多