Backbone.js 主干、木偶、Jasmine:如何测试jQuery延迟事件

Backbone.js 主干、木偶、Jasmine:如何测试jQuery延迟事件,backbone.js,jasmine,marionette,jquery-deferred,Backbone.js,Jasmine,Marionette,Jquery Deferred,我对Jasmine和Marionette非常陌生,正在寻找一些关于如何测试的帮助,甚至是思考如何测试我的应用程序的正确方法。欢迎任何指点 我有一个木偶控制器,用于获取模型、实例化视图并渲染它们。我使用此页面底部的方法,以便在呈现视图之前获取模型: 获取模型并显示视图的控制器方法如下所示: showCaseById: function(id){ App.models.Case = new caseModel({ id: id }); var promise = App.models.Ca

我对Jasmine和Marionette非常陌生,正在寻找一些关于如何测试的帮助,甚至是思考如何测试我的应用程序的正确方法。欢迎任何指点

我有一个木偶控制器,用于获取模型、实例化视图并渲染它们。我使用此页面底部的方法,以便在呈现视图之前获取模型:

获取模型并显示视图的控制器方法如下所示:

showCaseById: function(id){
  App.models.Case = new caseModel({ id: id });

  var promise = App.models.Case.fetch();
  $.when(promise).then(_.bind(this.showContentView, this));
},
如您所见,它在获取模型后调用showContentView。该方法如下:

showContentView: function(model){
  App.views.Body = new bodyView({
    model: App.models.Case
  });

  App.views.Body.on('case:update', this.submitCase, this);

  // this.layout is defined in the controller's initialize function
  this.layout.content.show(App.views.Body);
},
测试此功能的正确方法是什么?我想在承诺完成后测试showContentView函数的调用。我应该如何分解这个的规格


谢谢。

首先,监视您的showContentView方法并断言它已被调用:

it('showCaseById', function (done) {
    var controller = new Controller();
    spyOn(controller, 'showContentView');

    controller.showCaseById('foo');
    expect(controller.showContentView).toHaveBeenCalledWith(jasmine.any(caseModel));
});
其次,我建议您取消对fetch()的调用,这样您就不会访问网络,但现在它开始变得有点麻烦了:

function caseModel() {
    this.fetch = function () {
        // return a promise here that resolves to a known value, e.g. 'blah'
    };
}
现在,您可以有一个稍微强一点的断言,但这有点不可靠,因为您正在摆弄依赖项的内部结构:

expect(controller.showContentView).toHaveBeenCalledWith('blah');
通过重写caseModel,当您的控制器方法创建一个时,它将获得新版本而不是旧版本,并且您可以仅为该测试控制新版本的实现


有很多方法可以使这段代码更易于测试,但由于您似乎只是从测试开始,所以我不会详细介绍。当您进行更多的测试时,您肯定会自己发现这些问题。

首先,重要的是要了解
\uuu.bind(fn,context)
实际上并不调用fn。相反,它返回一个函数,调用该函数时将调用
fn()
上下文
将fn内部使用的对象定义为

这不是必需的,但您可以将
showCaseById
编写为:

showCaseById: function(id){
  App.models.Case = new caseModel({ id: id });

  var promise = App.models.Case.fetch();
  var fn = _.bind(this.showContentView, this);
  $.when(promise).then(fn);
},
正如我所说,这是不必要的,但现在您了解了
.bind()
返回函数,并且
$.when(promise)。然后(…)
接受函数作为其(第一)参数

要回答实际问题,您可以通过添加另一个
$.when(promise).then(…)
语句(使用您自己选择的测试函数)来确认
App.models.Case.fetch()
承诺已经实现

showCaseById: function(id){
  App.models.Case = new caseModel({ id: id });

  var promise = App.models.Case.fetch();
  $.when(promise).then(_.bind(this.showContentView, this));

  // start: test
  $.when(promise).then(function() {
    console.log("caseModel " + id + " is ready");//or alert() if preferred
  });
  // fin: test
},
第二个
$。当(承诺)。那么(…)
将不会干扰第一个;相反,这两者将按顺序执行。
console.log()
satatement将提供可靠的确认,确认已成功调用
this.showContentView
,并且应已进行初始渲染

如果此时或之后未呈现任何内容,则必须怀疑需要调试
this.showContentView