测试驾驶骨干视图事件

时间:2013-01-09 12:07:40

标签: backbone.js jasmine

我正在尝试使用Jasmine测试驱动视图事件,问题最好通过代码解释。

视图如下:

App.testView = Backbone.View.extend({
  events: { 'click .overlay': 'myEvent' },
  myEvent: function(e) {
    console.log('hello world')
  }

测试看起来像:

describe('myEvent', function() {
  it('should do something', function() {
    var view = new App.testView();
    view.myEvent();
    // assertion will follow
  });
});

问题是从不调用view.myEvent方法(没有任何日志记录到控制台)。我试图避免从DOM中触发。有人有过类似的问题吗?

1 个答案:

答案 0 :(得分:5)

(就像我在问题中评论的那样,您的代码看起来很好并且应该可以正常工作。您的问题不在您发布的代码中。如果您可以扩展代码示例并提供更多信息,我们可以再看一下以下是关于测试Backbone视图的更一般的建议。)

像你一样调用事件处理函数是一种合法的测试策略,但它有一些缺点。

  1. 它不会测试事件是否正确连接。您正在测试的是回调是否按预期执行,但它不会测试当您的用户与页面交互时实际触发的操作。
  2. 如果您的事件处理程序需要引用event参数,或者测试将无效。
  3. 我更喜欢从事件中一直测试我的观点:

    var view = new View().render();
    view.$('.overlay').click();
    
    expect(...).toEqual(...);
    

    就像你说的那样,在测试中操作DOM通常是不可取的,所以这种测试视图的方式要求view.render不会将任何内容附加到DOM上。

    实现此目的的最佳方法是将DOM操作留给负责初始化视图的代码。如果您没有为视图设置el属性(在View.extend定义或视图构造函数中),Backbone将创建一个新的,分离的DOM节点view.el。此元素的工作方式与附加节点类似 - 您可以操纵其内容并在其上触发事件。

    所以不是......

    View.extend({el: '#container'});
    

    ...或...

    new View({el:'#container'});
    

    ...您应该按如下方式初始化您的观点:

    var view = new View();
    $("#container").html(view.render().el);
    

    定义这样的观点有很多好处:

    1. 完全启用测试视图,而不将其附加到DOM。
    2. 视图可重用,您可以创建多个实例并将它们呈现给不同的元素。
    3. 如果您的render方法执行了一些复杂的DOM操作,则在分离的节点上执行它会更快。
    4. 从责任的角度来看,你可能会认为视图不应该知道它放在哪里,就像模型不应该知道它应该添加到哪个集合一样。这样可以更好地设计视图合成。
    5. 恕我直言,这种视图渲染模式是一般的最佳实践,而不仅仅是与测试相关的特殊情况。

相关问题