1

我正在使用 Jasmine 和 Sinon 为现有的 Backbone 应用程序开发一个测试套件,并且我正在测试我的路由器是否在某个路由上执行正确的操作。这是实际的路由功能:

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()which 是一种迭代视图集合的方法。

这是我的测试规范:

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我路由器中的方法。第三个测试是给我带来问题的那个。据我了解,因为我正在测试我的路由器而不是FavouriteMoviesView我应该删除视图以保持测试隔离。如果这是正确的假设,我的问题是存根没有renderFavourites方法,因为它是 stubbed out 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());

现在,您的 View “构造函数”将返回 a StubView,其中包含您正在调用的方法。所以这个带有 stubbed out 方法的 Backbone View 将被放置在router.favMoviesView-property 中。该favouritesViewStub属性仍然只包含“构造函数”-函数,因此您无法从那里访问这个存根方法。这就是为什么你必须从上一个测试中改变它:

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

像这样:

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

这样,您实际上将检查路由器的视图副本是否已经调用了两次该方法。

希望这对您有用,如果没有,请发表评论!我没有对此进行测试,因此可能存在一些问题,但我确信背后的逻辑是可行的。

于 2013-09-25T14:06:12.157 回答