20

バックボーン ビューがあり、ある要素のクリック イベントがその要素にバインドされた関数を呼び出すことを確認するテストを作成したいと考えています。私の見解は次のとおりです。

PromptView = Backbone.View.extend({
        id:"promptPage",
        attributes:{
            "data-role":"page",
            "data-theme":"a"
        },
        events:{
            "click #btnYes":    "answerYes",
            "tap #btnYes":      "answerYes"
        },
        render: function(){
            $(this.el).html(_.template($('#promptPage-template').html(), this.model.toJSON()));

            return this;
        },
        answerYes: function(){
            alert('yes');
        }
    });

私の仕様は次のとおりです。

beforeEach(function() {
            model = new PromptModel;
            view = new PromptView({model:model});
            loadFixtures('promptPage.tmpl');
        });

 it("should be able to answer a question with yes", function() {
                var button = $("#btnYes", view.render().el);
                expect(button.length).toBe(1);

                spyOn(view, 'answerYes');

                button.click();
                expect(view.answerYes).toHaveBeenCalled();

            });

ただし、上記のビュー定義はプロトタイプprotoでanswerYes メソッドを作成しますが、スパイはビュー内の実際のインスタンスで関数を作成するため、スパイである view.answerYes() と view.__proto__.answerYes, になります。これは私が実際にスパイしたいものです。

ビュー定義の answerYes メソッドをオーバーライドするようにスパイを作成するにはどうすればよいですか?

4

5 に答える 5

56

こんにちは、今日も同じ問題がありました。そして、私は解決策を見つけました。スパイされたメソッドを作成した後(answerYes)、ビューのイベントを更新して、その新しいスパイされたメソッドを呼び出す必要があります;):

[...]

    spyOn(view, 'answerYes');
    view.delegateEvents();

    ボタン.クリック();
    期待する (view.answerYes).toHaveBeenCalled();

[...]

デリゲート イベントの詳細

楽しむ!

于 2011-10-28T14:00:22.500 に答える
3

私は一般的に、フレームワーク コードが本来あるべきことを既に行っており、それを使用することのみをテストしていると想定したいので、イベント ハッシュを検証するテストを行うことは許容できると思います。自分のことをテストするためにバックボーン機能を複製していることに気付いた場合 (イベントの委任など)、実際に必要以上に統合テストに近づいている可能性があります。また、単体テストで非常に孤立した女性になるために、プロトタイプを多用しています。もちろん、そのすべてを実行する統合レイヤーを持つことは依然として重要ですが、フィードバック ループがテスト ドライビング フェーズには長すぎることがわかりました。

于 2012-11-21T15:01:51.277 に答える
3

answerYesこれにより、次のメソッドにスパイが作成されますPromptView

spyOn(PromtView.prototype, 'answerYes');
于 2013-07-05T14:33:51.557 に答える
1

TL;DR: プロトタイプではなく、インスタンス メソッドをスパイします。

テストを別の方法で設定する必要があると思います。ブロックにはあまりにも多くの懸念と期待がありit、テストで問題を引き起こす可能性があるグローバル名前空間も汚染しています。

beforeEach(function() {
  loadFixtures('promptPage.tmpl');

  var model = new PromptModel();
  this.view = new PromptView({model:model});
  this.view.render();

  this.button = this.view.$("#btnYes");
});

it("should render the button", function(){
  expect(this.button.length).toBe(1);
});

it("should be able to answer a question with yes", function() {
  spyOn(this.view, 'answerYes');

  this.button.click();
  expect(this.view.answerYes).toHaveBeenCalled();
});

ボタンの長さを厳密に期待する必要はありません。ボタンに長さがない (見つからない) 場合は、他のエラーが発生します。しかし、ビューが正しくレンダリングされていないことを簡単に把握できるようにするために、そこに表示したい場合があります。

viewまた、これまで行ってきたように、インスタンスをスパイする必要があります。の定義はプロトタイプにメソッドをPromptView追加しanswerYesますが、スパイしたいのはプロトタイプではなくビューインスタンスです。

プロトタイプのメソッドをスパイすると、テストでこのビューを使用しようとするたびに、answerYesメソッドは実際のメソッドではなくスパイになります。これはいいように聞こえるかもしれませんが、このメソッドを複数回呼び出すと、有効なスパイ データにアクセスできなくなるため、問題が発生します。その 1 つのスパイのすべての呼び出しが単純に蓄積されます。プロトタイプメソッドを2回スパイしようとすると、スパイのスパイになってしまう可能性があり、これは奇妙なことであり、問​​題を引き起こす可能性があります。

于 2011-10-26T12:55:48.193 に答える
0

spyOn の使用に問題がある場合は、スパイの作成を検討してください。次のようなものです:

var eventSpy;
eventSpy = jasmine.createSpy('eventSpy');
view.$el.on('myCustom:event', eventSpy);
于 2015-06-25T18:20:47.733 に答える