0

我发现导航到不同 URL 以进行查看和路由器行为测试的唯一方法是使用 Backbone.history.loadUrl()。Backbone.history.navigate('#something', true) 和 router.navigate('#something, {trigger: true, replace: true} 及其任何组合在测试中不起作用。我的应用程序不使用 pushstate。

这在单个测试的上下文中可以正常工作。

describe('that can navigate to something as expected', function(){
  beforeEach(function() {
    this.server = sinon.fakeServer.create();
    //helper method does my responds to fetches, etc. My router in my app is what starts Backbone.history
    this.router = initializeBackboneRouter(this.server, this.fixtures, false);
  }); 
  afterEach(function(){
    this.server.restore();
    Backbone.history.stop();
    Backbone.history.loadUrl('#');
  });

  it('should create the view object', function(){
    Backbone.history.loadUrl('#something');
    expect(this.router.myView).toBeDefined();
  });
});

在测试期间,您可以看到主干按照预期将哈希附加到 URL: localhost:8888/#something 取决于测试。

不幸的是,loadUrl 似乎在测试行为方式上引入了很多不一致的地方。在我的一项涉及一些异步 JS 的测试中,我需要等待 AJAX 调用完成,大约 50% 的时间失败,超时或有时预期未定义。如果我排除了我期望在那里的数据,那么我知道这不是 BS 测试。

it('should add the rendered html to the body', function(){
  runs(function(){
    Backbone.history.loadUrl('#something');
  });
  waitsFor(function(){
    var testEl = $('#title');
    if(testEl.length > 0){ return true; }
  }, 1000, 'UI to be set up');
  runs(function(){
    var testEl = $('#title');
    expect(testEl.text()).toEqual(this.router.model.get(0).title);
  });

});

这里重要的一点是,它仅在所有测试都运行时才会失败;它自己运行它通过 100% 的时间。

那么我的问题是:Backbone.history.loadUrl 是围绕 jasmine 中的主干应用程序进行编程导航的不好方法吗?我觉得我已经尝试了一切来模拟用户访问特定 URL。我的拆解不正确吗?我试过没有 Backbone.history.loadUrl('#'); 并得到不同的行为,但没有通过测试。

核心问题似乎是,在几个、数百甚至几个 jasmine 测试的上下文中,Backbone.history 并没有清除自己,而是作为自身的一个实例而存在,而不是在每次测试时都完全重新初始化。

4

1 回答 1

0

这糟透了。解决方案是稍微编辑我的代码以添加一个加载完成标志,当我确定 DOM 已 100% 完成加载时,该标志设置为 true。

然后我编写了一个辅助函数,等待该标志在每个测试根目录的 beforeEach 函数中为真。

var waitForLoadingComplete = function(view){
  waitsFor(function(){
    if(view.loadingComplete == true){return true;}
  }, 100, 'UI Setup Finished');
}

之后,我将我的设置重构为一个辅助函数:

var setupViewTestEnvironment = function(options) {
  var temp = {};
  temp.server = sinon.fakeServer.create();
  temp.router = initializeBackboneRouter(temp.server, options.fixture);
  waitForLoadingComplete(temp.router.initialview);
  runs(function(){
    Backbone.history.loadUrl(options.url);
    temp.view = temp.router[options.view];
    temp.model = temp.router[options.model];    
    waitForLoadingComplete(temp.view);
  });
  return temp;
}

示例使用:

  beforeEach(function() {
    this.testEnv = setupViewTestEnvironment({
      url: '#profile', 
      view: 'profileIndex', 
      model: 'myModel', 
      fixture: this.fixtures
    });  
  }); 

之后,我看到我已经加载了一个视图,我可以确定它已经完成加载,所以我可以在 DOM 上测试东西或我想做的任何其他事情。

于 2013-09-25T22:31:58.807 回答