【问题标题】:Test Marionette vent.on Listener测试 Marionette vent.on 监听器
【发布时间】:2014-05-12 10:28:36
【问题描述】:

我有一个Layout,其中有一个vent.on 调用,它会在模型​​启动时进行设置。

initialize: () ->
  App.vent.on("deciseconds:updated", this.updateDVR)

 updateDVR: () ->
  console.log 'this updateDVR is called'

我想确保this.updateDVR 在我的应用程序中正确连接。在我的测试中,我有这个:

beforeEach ->
  this.showDvr = new Arc.DvrApp.Show.DvrView()
  spyOn(this.showDvr, 'updateDVR')

it "calls updateDvr when new data comes in", ->
  Arc.vent.trigger("deciseconds:updated")
  expect(this.showDvr.updateDVR).toHaveBeenCalled()

这个规范失败了,但是当我检查我的日志时,我看到了this updateDVR is called,这是我在updateDVR 函数中登录的行。所以我知道该函数正在被调用。

我直接调用updateDVR,规范通过:

it "calls updateDvr when new data comes in", ->
  this.showDVR.updateDVR()
  expect(this.showDvr.updateDVR).toHaveBeenCalled()

我认为vent 可能被视为异步函数,因此我尝试在expect 子句之前等待几秒钟,看看是否可行,但没有:

it "calls updateDvr when new data comes in", ->
  Arc.vent.trigger("deciseconds:updated")
  setTimeout(myCheck, 3000)

myCheck = () ->
  expect(this.showDvr.updateDVR).toHaveBeenCalled()

【问题讨论】:

  • 我认为 Jasmine 间谍取代了原来的功能,不是吗? (你必须调用 .andCallThrough() 让它调用原始函数。)所以我不确定你的原始 updateDVR() 是如何被调用来在这个测试中创建日志消息的。当您的间谍不在位时,另一个测试是否可以调用 updateDVR() 并记录该消息?
  • @MikeStapp 很好地调用了间谍接管该功能的控制权。让我看看另一个规范是否给了我们一个误报
  • @MikeStapp 你是一个人。如果我调用Arc.vent.trigger,我会得到默认的方法行为,但如果我调用this.showDvr.updateDVR,我什么也得不到(预期的,因为间谍没有传递给常规函数)。出于某种原因,spy 没有被放置在对象上。它似乎只有在测试框架中有上下文
  • Arc.ventApp.vent 的别名吗?
  • @pdoherty926 是的。具体来说,我们称我们的“应用程序”Arc,因此它是包含所有 Marionette/Backbone 信息的窗口变量

标签: backbone.js jasmine marionette


【解决方案1】:

initialize 函数中对App.vent.on 的调用将引用 传递给视图实例的this.updateDVR 函数——这发生在测试的spyOn(this.showDvr, ...) 之前beforeEach .因此,当您触发事件时,触发器调用保留对实际 updateDVR 函数的引用,而不是间谍。

您应该能够通过将回调函数传递给App.vent.on 调用来修复它,就像这样(抱歉,javascript,我不是coffeescripter!):

initialize: function () {
    var that = this;
    // hold onto the callback so we can unregister it in App.vent.off, too 
    this.onUpdateCb = function() { that.updateDVR() };
    App.vent.on("deciseconds:updated", this.onUpdateCb );

    // if this is a view, stop listening for App.vent when the view closes
    this.listenTo(this, 'close', function() { App.vent.off("deciseconds:updated", this.onUpdateCb ) } );
}

这将使事件处理程序在事件触发时查找名为“updateDVR”的符号,并按照您的测试预期调用您的间谍。

编辑:已更新以保留 this.onUpdateCb,以便我们可以在关闭时取消注册侦听器。

【讨论】:

  • 这太棒了!拥有回调函数而不仅仅是以前的引用有什么缺点吗?性能或其他一些奇怪的警告?
  • 额外的函数调用对性能的影响非常小,但仅此而已。不应该真的很明显,因为您已经产生了 trigger() 的少量开销。哦——我的代码中有一个小错误。 :-) 现在,当您关闭视图时,您将无法 App.vent.off(),因为我使用的是匿名函数。我将编辑我的答案以修复它。
  • 非常酷。谢谢(你的)信息。 vent.off 非常受欢迎。我得调查一下,看看我在哪里做过类似的坏事
  • listenTo 是所有on/off 的完美替代品:this.listenTo(App.vent, "deciseconds:updated", this.onUpdateCb) ...它还可以绑定处理程序,这样您就可以避免跟踪that
猜你喜欢
  • 2019-07-18
  • 1970-01-01
  • 1970-01-01
  • 2018-06-13
  • 2018-03-17
  • 2019-12-31
  • 2014-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多