web-dev-qa-db-ja.com

このテストを実行すると、なぜこのシノンスパイが呼び出されないのですか?

私はバックボーンモデルを持っています:

class DateTimeSelector extends Backbone.Model

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

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

そして、 jasminsinon.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()

ブラウザで使用すると動作するようですが、テストに合格できないようです。誰かが私を啓発できますか?

21
David Tuite

duckyfuzz、この問題が発生しているのは、スパイを作成しているときに(実際には元の関数をラップし、メソッド呼び出しを追跡するサービスを挿入するための間接レベルを作成している)、イベントのバインドがすでに行われているためです。つまり、スパイが元の関数をラップしたとしても、イベントバインディングは、ラップされたスパイではなく、元の関数を参照します。したがって、テストすると、元の関数はイベントトリガーで実行されますが、スパイトラッキングは1レベル上にあり、実行されません。

イベントバインディングが実際にラップされたスパイ関数を指していることを確認するには、モデルオブジェクトを作成する前にスパイを作成する必要があります(ビューをテストしている場合も同様です)。これを行うには、クラスのprototype。 "method"にスパイを作成します。

beforeEach->セクションの前@ datetime = new DateTimeSelector()スパイを作成します:@ 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プラグインを使用している場合は、構文に問題はありません。

48
vadimich

ジャスミンとシノンのモック構文を混ぜ合わせています。

合格テストでは、シノンスパイがプロパティcalledOnceを公開しますが、ジャスミン風の関数toHaveBeenCalledOnce()を使用しています。この関数はシノンスパイには存在しないため、基本的にアサートは行われません。

失敗したテストでは、シノンスパイでジャスミンスパイ関数toHaveBeenCalled()を呼び出しています。 Jasmineには、スパイを作成するための独自の構文があります:spyOn(obj, 'method');

0
Eric Bock