使用 mocha/chai 进行测试时收到 UnhandledPromiseRejectionWarning

新手上路,请多包涵

所以,我正在测试一个依赖于事件发射器的组件。为此,我想出了一个使用 Promises 和 Mocha+Chai 的解决方案:

it('should transition with the correct event', (done) => {
  const cFSM = new CharacterFSM({}, emitter, transitions);
  let timeout = null;
  let resolved = false;
  new Promise((resolve, reject) => {
    emitter.once('action', resolve);
    emitter.emit('done', {});
    timeout = setTimeout(() => {
      if (!resolved) {
        reject('Timedout!');
      }
      clearTimeout(timeout);
    }, 100);
  }).then((state) => {
    resolved = true;
    assert(state.action === 'DONE', 'should change state');
    done();
  }).catch((error) => {
    assert.isNotOk(error,'Promise error');
    done();
  });
});

在控制台上我得到一个“UnhandledPromiseRejectionWarning”,即使拒绝函数被调用,因为它立即显示消息“AssertionError:承诺错误”

(节点:25754)UnhandledPromiseRejectionWarning:未处理的承诺

拒绝(拒绝 id:2):AssertionError:承诺错误:预期

{ Object (message, showDiff, …) } 是假的

  1. 应该使用正确的事件进行转换

然后,2秒后我得到

错误:超过 2000 毫秒的超时。确保 done() 回调是

在这个测试中被调用。

自从执行了 catch 回调之后,这更奇怪了(我认为由于某种原因,断言失败阻止了其余的执行)

现在有趣的是,如果我注释掉 assert.isNotOk(error...) 测试运行良好,控制台中没有任何警告。在执行捕获的意义上,它仍然“失败”。

但是,我仍然无法用承诺来理解这些错误。有人可以启发我吗?

原文由 Jzop 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 732
1 个回答

问题是由此引起的:

 .catch((error) => {
 assert.isNotOk(error,'Promise error');
 done();
 });

如果断言失败,则会抛出错误。这个错误将导致 done() 永远不会被调用,因为代码在它之前出错了。这就是导致超时的原因。

“未处理的承诺拒绝” 也是由失败的断言引起的,因为如果在 catch() 处理程序中抛出错误, _并且没有后续的 catch() 处理程序_,错误将被吞没(如 本文所述)。 UnhandledPromiseRejectionWarning 警告提醒您注意这一事实。

一般来说,如果你想在 Mocha 中测试基于 Promise 的代码,你应该依赖 Mocha 本身已经可以处理 Promise 的事实。你不应该使用 done() ,而是从你的测试中返回一个承诺。然后 Mocha 将自己捕获任何错误。

像这样:

 it('should transition with the correct event', () => {
 ...
 return new Promise((resolve, reject) => {
 ...
 }).then((state) => {
 assert(state.action === 'DONE', 'should change state');
 })
 .catch((error) => {
 assert.isNotOk(error,'Promise error');
 });
 });

原文由 robertklep 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题