(就像我在问题中评论的那样,您的代码看起来不错并且应该可以工作。您的问题不在您发布的代码中。如果您可以扩展您的代码示例并提供更多信息,我们可以再看看它。下面是更多关于测试 Backbone 视图的一般建议。)
像你一样调用事件处理函数是一种合法的测试策略,但它有几个缺点。
- 它不会测试事件是否正确连接。您正在测试的是回调执行了它应该做的事情,但它没有测试当您的用户与页面交互时该操作是否被实际触发。
- 如果您的事件处理程序需要引用
event
参数或测试将不起作用。
我更喜欢从事件开始测试我的观点:
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);
像这样定义视图有很多好处:
- 完全启用测试视图而不将它们附加到 DOM。
- 视图变得可重用,您可以创建多个实例并将它们呈现给不同的元素。
- 如果您的
render
方法执行一些复杂的 DOM 操作,那么在分离节点上执行它会更快。
- 从责任的角度来看,您可以争辩说视图不应该知道它的放置位置,就像模型不应该知道它应该添加到哪个集合一样。这加强了视图组合的更好设计。
恕我直言,这种视图渲染模式是一种通用的最佳实践,而不仅仅是与测试相关的特殊情况。