質問

I have a Layout that has a vent.on call in it that gets setup on model initiation.

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

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

I want to make sure this.updateDVR is hooked up correctly in my app. In my tests I have this:

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 spec is failing, but when I check my log I am seeing this updateDVR is called, the line I was logging in the updateDVR function. So I know the function is being called.

It I directly call updateDVR, the spec passes:

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

I thought the vent might be treated as an asynchronous function, so I tried waiting a few seconds before the expect clause to see if that would work, but it didn't:

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

myCheck = () ->
  expect(this.showDvr.updateDVR).toHaveBeenCalled()
役に立ちましたか?

解決

The call to App.vent.on in your initialize function passes a reference to the view instance's this.updateDVR function -- and that happens right before you spyOn(this.showDvr, ...) in the test's beforeEach. So when you trigger the event, the trigger calls that retained reference to the actual updateDVR function, not the spy.

You should be able to fix it by passing a callback function to the App.vent.on call, like so (sorry for the javascript, I'm not a 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 ) } );
}

That will make the event handler look up the symbol named "updateDVR" at the time the event is triggered, & it will call your spy as your test expects.

Edit: Updated to retain this.onUpdateCb so we can unregister the listener on close.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top