22

我有一个骨干模型:

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

当我在浏览器中使用它时它似乎可以工作,但我似乎无法通过测试。任何人都可以启发我吗?

4

2 回答 2

53

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

要确保事件绑定实际上指向包装的 spy 函数,您必须在创建模型对象之前创建 spy(如果您正在测试视图,也是如此)。为此,请在类的原型“方法”上创建间谍:

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

请务必更改您的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 插件,那么您的语法很好

于 2012-01-26T01:10:02.583 回答
0

您将 jasmine 和 sinon 的模拟语法混合在一起。

在您的通过测试中,您的 sinon 间谍暴露了该属性calledOnce,但您使用的是 jasmine-esque 函数toHaveBeenCalledOnce()。sinon spy 上不存在此功能,因此基本上没有发生断言。

在你失败的测试中,你toHaveBeenCalled()在你的 sinon 间谍上调用了 jasmine spy 函数。Jasmine 有自己的创建间谍的语法:spyOn(obj, 'method');

于 2011-12-15T20:37:16.067 回答