javascript - 为什么当我运行此测试时,这个 sinon spy 没有被调用?

标签 javascript backbone.js jasmine coffeescript backbone-events

我有一个 Backbone 模型:

class DateTimeSelector extends Backbone.Model

  initialize: ->
    @bind 'change:date', @updateDatetime
    @bind 'change:time', @updateDatetime

  updateDatetime: =>
    # do some stuff with the sate and time

我使用 jasmin 对该代码进行了一些测试和 sinon.js

describe "DateTimeSelector", ->
  beforeEach ->
    @datetime = new DateTimeSelector()

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

      afterEach ->
        @datetime.updateDatetime.restore()

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

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

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

当我在浏览器中使用它时,它似乎可以工作,但我似乎无法通过测试。谁能帮我解答一下吗?

最佳答案

duckyfuzz,您遇到这个问题是因为当您创建 spy 时(它实际上包装了原始函数并创建了一个间接级别以插入其跟踪方法调用的服务),事件的绑定(bind)已经发生。这意味着即使 spy 包装了原始函数,事件绑定(bind)也会引用原始函数而不是包装的 spy 。因此,当您测试时,原始函数会在事件触发器上执行,但 spy 跟踪是上面一级的并且不会执行。

为了确保事件绑定(bind)实际上指向包装的 spy 函数,您必须在创建模型对象之前创建 spy (如果您正在测试 View ,则同样如此)。为此,请在原型(prototype)上创建 spy 。类的“方法”:

@datetime = new DateTimeSelector() 之前的 beforeEach -> 部分中创建 spy :@updateSpy = sinon.spy(DateTimeSelector.原型(prototype),'updateDatetime')

请务必更改将原型(prototype)恢复正常的 afterEach -> 部分,如下所示:@updateSpy.restore()

这应该是您的代码:

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() 

顺便说一句,如果您使用 jasmin-sinon.js 插件,那么您的语法就很好

关于javascript - 为什么当我运行此测试时,这个 sinon spy 没有被调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8441612/

相关文章:

jquery - trigger.io:我应该使用 request.ajax 还是 jQuery.ajax

javascript - 编写 JavaScript 测试来测试其他函数的调用,而不实际调用它们

javascript - 服务 promise 不解决 karma

javascript - 在生产中的 Vue 在按钮中使用 v-text 时会破坏应用程序

c# - 如果中间发生页面更改,AJAX 请求/响应的数据会发生什么情况

javascript - 将平行坐标代码从 d3.js v3.5.16 移植到 4.0

php - 如何每十秒刷新一次 php 脚本?

javascript - 使用backbone.js获取集合,但未设置每个模型的id

jquery - 为什么 Backbone 的事件 obj 缺少属性?

unit-testing - 使用 Observable (Angular 2) 模拟服务时测试出错