【问题标题】:Ember concurrency timeout hanging in qunitEmber 并发超时挂在 qunit
【发布时间】:2020-02-19 03:44:15
【问题描述】:

在 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,但它并没有真正的帮助,因为它只处理单元测试。

【问题讨论】:

    标签: ember.js concurrency qunit ember-qunit ember-concurrency


    【解决方案1】:

    您没有做错任何事情,这是 ember-concurrency 的常见问题。 Ember-concurrency 的 timeout() 函数依赖于 Ember.run.later() 来创建超时,幸运或不幸的是,Ember 的测试套件知道使用 Ember.run.later() 创建的所有计时器,并将等待所有计时器稳定后再让测试继续。由于您的代码使用无限循环,因此您的计时器将永远不会稳定,因此测试会挂起。在 Ember 指南 here 中有一个关于测试异步代码的不错的小部分。

    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 文档中,所以我个人不会依赖它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多