2012-08-07 7 views
9

Backbone Routerで特定のルート上で適切なメソッドを呼び出していることを確認するためにメソッド呼び出しを呼び出すことに問題がある。Backbone.jsでスパイするジャスミンで電話をかける

抜粋

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

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

ルータ

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

テストからすべてが最後のテスト "のインデックスを呼び出す必要があります" 以外渡します。 「スパイインデックスが呼び出されたと予想されます」というメッセージで失敗します。 アイブ氏は、私はまた、「router.indexが呼び出された」オリジナルRouter.index関数からテスト出力に

感謝をログ出力を見ることができる他の変異体

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

を試してみました!

EDIT: 一つの解決策

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

答えて

15

は、2つのオプションがありますworking jsFiddleと私に多くの時間があり、質問はすでに@MarkRushakoffによって答えられています。

まだコメントがあります。

バックボーンがルートをバインドする方法は、テストするのが非常に困難です。

ポイントはルータ方法ルータインスタンスに直接呼び出されていないことで、方法は、コールバックとしてtaked、実行、check the Backbone.Router.route code待っ内部Backbone.history.routeに格納されています。

この操作は一瞬で行われRouterはインスタンス化しているので、あなたはspyがアクティブ化された後もBackbone.history.startを遅らせるために持っているためにあなたは、あなたが参照をインスタンス化する前に、あなたのRouter.methodspyする必要があります。

ルータインスタンスが作成される前に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実装が直感的なデザインをしていないと思います。

+1

ありがとう!そのように見えます:) – eldewall

+0

これはルートのトリガーをテストする実行可能な方法ではありません。これは、インデックス関数がコールバックとしてルーターにバインドされたものであり、ルートがトリガーされたときに関数が実際に呼び出されるということではありません。 「[this S.O.ルータがURLと一致したときに対応するルート関数が呼び出されたことを確認する方法については、[post](http://stackoverflow.com/questions/9215737/testing-routers-in-backbone-js-properly)を参照してください。 – louism2

4

コンソールを見ている場合は特に、私は(これはあなたがルートハッシュを使用するときにバックボーンがルーティング方法に結合する方法に関係しているかなり確信していますログは正しく出力されます)。つまり、ルータは元のindexメソッドにバインドしていますが、あなたのスパイは「現在の」indexメソッドを置き換えています。ルータがルートに結合する前に、プロトタイプのindex方法に

  • スパイ(難しいかもしれない)

    • spyOn(@router, "index")::それはあまりにもかかったspyOn(App.router.prototype, "index"); @router.navigate('', true); expect(App.router.prototype.index).toHaveBeenCalled();
  • +0

    ありがとうございます:)オプション番号2は実行可能です。スパイは、ルータの新しいインスタンスが作成される前に追加する必要があります。私はそれがOKだと思います! – eldewall

    +0

    オプション1私は_routes binding_が_initialize_で行われているために不可能だと思うので、インスタンスへの参照を持っている瞬間にバインディングはすでに完了しています。 – fguillen

    関連する問題