ember.js Ember并发超时在qunit中挂起

2ic8powd  于 2022-11-05  发布在  其他
关注(0)|答案(1)|浏览(132)

在Ember中,我有一个组件,它可以启动一个无休止的投票,以保持一些数据的最新状态。

export default Component.extend({
  pollTask: task(function * () {
    while(true) {
      yield timeout(this.get('pollRate'));
      this.fetchSomeData();
    }
  }).on('init')
})

这会导致预先存在的接受度测试卡在这个工作中,而且永远执行,即使它应该异步执行也是如此。测试如下所示:

test('my test', async function(assert) {
  mockFindRecord(make('fetched-model'));

  await visit('/mypage'); // gets stuck here
  await typeIn('input', 'abc123');

  assert.ok(somethingAboutThePage);
});

起初我以为我对请求的模拟是错误的,测试只是超时了,但实际上它正确地轮询了数据。删除此任务会使验收测试正常完成。
手动测试这个似乎工作得很好,没有什么会卡住。为什么会发生这种情况,解决这个问题的正确方法是什么?
看过Unit testing ember-concurrency tasks and yields,但它并没有真正的帮助,因为它只处理单元测试。

qni6mghb

qni6mghb1#

您没有做错任何事情,这是ember并发的一个常见问题。ember并发的timeout()函数依赖于Ember.run.later()创建超时,幸运的是,Ember的测试套件知道使用Ember.run.later()创建的所有计时器,并将等待所有计时器稳定下来,然后让测试继续。因为你的代码使用了一个无限循环,你的计时器永远不会稳定,所以测试挂起。在Ember指南中有一个关于测试异步代码的小章节。
在ember-concurrency文档中有一节是关于here这个问题的,我建议你仔细阅读一下,看看他们对如何解决这个问题的建议,尽管当时似乎还没有真实的优雅的解决方案。
最快也可能是最简单的方法是检查应用程序是否正在测试(我知道,这很恶心):

pollTask: task(function * () {
    while(true) {
      yield timeout(this.get('pollRate'));
      this.fetchSomeData();
      if (Ember.testing) return; // stop polling to prevent tests from hanging
    }
  }).on('init')

您也可以尝试在tests/helpers/start-app.js文件中调用Ember.run.cancelTimers()(该部分中的另一个建议):

window._breakTimerLoopsId = Ember.run.later(() => {
  Ember.run.cancelTimers();
}, 500);

但它似乎没有出现在API文档中,所以我个人不会依赖它。

相关问题