9

特定のルートで正しいメソッドを呼び出すことを確認するために、バックボーン ルーターでメソッド呼び出しをスパイすることに問題があります。

テストからの抜粋

describe 'Router', ->
    beforeEach ->
        @router = new App.Router()
        Backbone.history.start()

    afterEach ->
        Backbone.history.stop()

    describe 'routes', ->
         it 'should be defined', ->
              expect(@router.routes).toBeDefined()

         describe 'default route', ->
             it 'should be defined', ->
                  expect(@router.routes['']).toBeDefined()

             it 'should call index', ->
                 spy = spyOn(@router, "index")
                 @router.navigate('', true)
                 expect(spy).toHaveBeenCalled()

ルーター

class App.Router extends Backbone.Router
    routes:
        '' : 'index'

    index: ->
        console.log "router.index has been called"

最後のテスト「インデックスを呼び出す必要がある」を除いて、すべてが合格します。「スパイインデックスが呼び出されると予想されます」というメッセージで失敗します。私は他の変種を試しました

it "should call index", ->
    spyOn(@router, "index")
    @router.navigate('', true)
    expect(@router.index).toHaveBeenCalled()

元の Router.index 関数からのテスト出力で、「router.index has been called」というログ出力も確認できます。

ありがとう!

編集:1つの解決策

describe '#1 Solution', ->
    it 'should call index', ->
        spyOn(App.Router.prototype, "index")
        @router = new App.Router()
        Backbone.history.start()
        @router.navigate('', true)
        expect(App.Router.prototype.index).toHaveBeenCalled()
4

2 に答える 2

15

動作する jsFiddleを用意するのに時間がかかりすぎて、質問は @MarkRushakoff によって既に回答されています。

それでもコメントはあります。

バックボーンがルートをバインドする方法により、テストが非常に困難になります。

ポイントは、ルーターメソッドがルーターインスタンスで直接呼び出されないことです。メソッドはコールバックとして取得され、Backbone.history.route実行を待機する内部に格納されます。Backbone.Router.route コードを確認してください

この操作はRouterがインスタンス化された瞬間に行われるため、参照をインスタンス化する前にRouter.methodspyを実行する必要があるため、がアクティブ化された後も遅延する必要があります。Backbone.history.startspy

spyルーター インスタンスを作成する前にを宣言する必要があるため、クラスレベルで行う必要があります。

これは私が思いついた最も簡単な解決策です:

describe("Router", function() {
  afterEach( function(){
    Backbone.history.stop();
  });

  it("should call index", function(){
    spyOn(App.Router.prototype, "index")
    var router = new App.Router(); // instance created after spy activation
    Backbone.history.start();      // it has to start after the Router instance is created

    router.navigate('', true);

    expect(App.Router.prototype.index).toHaveBeenCalled();  
  });
});

Backbone.Router結論として、実装は直感的な設計ではないと思います。

于 2012-08-07T15:38:15.827 に答える