Why is this sinon spy not being called when I run this test?

duckyfuzz, you are experiencing this problem because when you are creating the spy (which actually wraps the original function and creates a level of indirection to insert its services of tracking method invocation) the binding of the events has already taken place. Which means that even though the spy wrapped the original function the event binding references the original function and not the wrapped spy. Hence, when you test, the original function gets executed on the event trigger but the spy tracking is one level above and is not executed.

To make sure that the event binding is actually pointing to the wrapped spy function you have to create the spy before create the model object (same goes if you are testing views). To do that create the spy on the prototype."method" of the class:

in the beforeEach -> section before @datetime = new DateTimeSelector() create the spy: @updateSpy = sinon.spy(DateTimeSelector.prototype, 'updateDatetime')

be sure to change your afterEach -> section where you return the prototype back to normal, like so: @updateSpy.restore()

this should be your code:

describe "DateTimeSelector", ->
  beforeEach ->
    @updateSpy = sinon.spy(DateTimeSelector.prototype, 'updateDatetime')
    @datetime = new DateTimeSelector()

  afterEach ->
    @updateSpy.restore()

  # passes
  it "should be called when we call it", ->
    @datetime.updateDatetime()
    expect(@updateSpy).toHaveBeenCalledOnce()

  # should pass now
  it "should be called when we trigger it", ->
    @datetime.trigger 'change:date'
    expect(@updateSpy).toHaveBeenCalled()

  # should pass now
  it "should be called when we set the date", ->
    @datetime.set { date: new Date() }
    expect(@updateSpy).toHaveBeenCalled() 

BTW, if you are using jasmin-sinon.js plugin then your syntax is fine