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

前端 未结 2 706
盖世英雄少女心
盖世英雄少女心 2020-12-02 15:44

I have a Backbone Model:

class DateTimeSelector extends Backbone.Model

  initialize: ->
    @bind \'change:date\', @updateDatetime
    @bind \'change:tim         


        
相关标签:
2条回答
  • 2020-12-02 16:25

    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

    0 讨论(0)
  • 2020-12-02 16:27

    You're mixing the mocking syntax of jasmine and sinon together.

    In your passing test your sinon spy exposes the property calledOnce but you're using a jasmine-esque function toHaveBeenCalledOnce(). This function doesn't exist on the sinon spy so essentially no assert is taking place.

    In your failing tests you're calling the jasmine spy function toHaveBeenCalled() on your sinon spy. Jasmine has its own syntax for creating a spy: spyOn(obj, 'method');

    0 讨论(0)
提交回复
热议问题