1

Jasmine と Sinon を使用して既存のバックボーン アプリケーションのテスト スイートに取り組んでおり、ルーターが特定のルートで正しいアクションを実行することをテストしています。実際のルート関数は次のとおりです。

favourites: function()
{
    //Dont re-initialize the favourites view as there is no need.
    //Instead, just render the favourite movies
    if ( ! this.favMoviesView)
    {
        this.favMoviesView = new cinephile.Views.FavouriteMoviesView({
            collection: cinephile.favouriteMovies
        });
    }
    else
    {
        this.favMoviesView.renderFavourites();
    }

    $('#content').html(this.favMoviesView.el);
},

私のテストスイートでは、お気に入りルートに移動するときにルートthis.favMoviesViewが一度作成され、それが存在する場合は再初期化せずthis.favMoviesView.renderFavourites()、ビューのコレクションを反復処理するメソッドを呼び出すだけであると主張したいと思います。

これが私のテスト仕様です:

describe('cinephile.Routers.CinephileRouter', function () {

    beforeEach(function () {

        this.router = new cinephile.Routers.CinephileRouter();
        this.routeSpy = sinon.spy();

        try
        {
            Backbone.history.start({ silent : true });
        }
        catch(e) {}

        this.router.navigate('elsewhere');

        this.favouritesViewStub = sinon.stub(cinephile.Views, 'FavouriteMoviesView')
            .returns(new Backbone.View());
    });

    afterEach(function () {
        this.favouritesViewStub.restore();
    });

    describe('Favourites Route', function() {

        it('should load the favourites on /favourites', function () {

            this.router.bind('route:favourites', this.routeSpy);
            this.router.navigate('favourites', true);

            expect(this.routeSpy.calledOnce).toBeTruthy();
            expect(this.routeSpy.calledWith()).toBeTruthy();
        });

        it('creates a favourites view if one doesn\'t exist', function () {
            this.router.favourites();
            expect(this.favouritesViewStub.calledOnce).toBeTruthy();
        });

        it('Reuses the favourites view if one does exist and reset it\'s collection', function () {
            this.router.favourites();
            this.router.favourites();

            expect(this.favouritesViewStub.calledOnce).toBeTruthy();
            expect(this.favouritesViewStub.renderFavourites).toHaveBeenCalledTwice();
        }); 
    });
});

favourites最初の 2 つのテストは成功し、ルーターのメソッドを正しく記述していると信じています。3番目のテストは、私に問題を与えるものです。私が理解しているように、ルーターをテストFavouriteMoviesViewしているのではなく、テストを分離しておくためにビューをスタブ化する必要があります。それが正しい仮定である場合、私の問題は、スタブがスタブ化さrenderFavouritesれているため、スタブにメソッドがないことになりBackbone.View()ます。

この特定の問題を解決するにはどうすればよいですか。また、もしよろしければ、概念的な何かが欠けていると思いますので、私が理解していないことを自由に説明してください。

乾杯。

4

1 に答える 1

1

あなたの問題は、モック関数内で何かをモックしたいということです。私が提案するのは、これの代わりに...

this.favouritesViewStub = sinon.stub(cinephile.Views, 'FavouriteMoviesView').returns(new Backbone.View());

...これを持っています:

var StubView = Backbone.View.extend({
  renderFavourites: sinon.stub()
});
this.favouritesViewStub = sinon.stub(cinephile.Views, 'FavouriteMoviesView').returns(new StubView());

これで、ビューの「コンストラクター」はStubView、呼び出しているメソッドがスタブ化された を返します。したがって、スタブ化されたメソッドを含むこのバックボーン ビューは、プロパティに配置されrouter.favMoviesViewます。プロパティにはfavouritesViewStubまだ「コンストラクター」関数のみが含まれているため、そこからこのスタブ化されたメソッドにアクセスすることはできません。これが、前回のテストからこれを変更する必要がある理由です。

expect(this.favouritesViewStub.renderFavourites).toHaveBeenCalledTwice();

このようなものに:

expect(this.router.favMoviesView.renderFavourites).toHaveBeenCalledTwice();

このようにして、ルーターのビューのコピーにメソッドが2回呼び出されたかどうかを実際に確認します。

これがうまくいくことを願っています。うまくいかない場合はコメントしてください!私はこれをテストしなかったので、いくつかの問題がある可能性がありますが、背後にあるロジックが機能していると確信しています.

于 2013-09-25T14:06:12.157 に答える