提问者:小点点

在使用mocha/chai进行测试时获取UnhandledPromiseRejectionWarning


所以,我在测试一个依赖于事件发射器的组件。为此,我想出了一个解决方案,使用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”,尽管reject函数正在被调用,因为它会立即显示消息“assertionError:Promise Error"

(Node:25754)UnhandledPromiseRejectionWarning:UnhandledPromiseRejectionWarning:UnhandledPromiseRejection(rejection ID:2):AssertionError:promise Error:{Object(message,showDiff,。。。)}应为

然后,两秒钟后我

错误:超时2000ms。确保在此测试中调用了done()回调。

null

null


共3个答案

匿名用户

null

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

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

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

null

像这样:

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');
  });
});

匿名用户

我在和Sinon打短板的时候出现了这个错误。

修复方法是在解析或拒绝带有存根的承诺时使用npm包sinon-as-promedied。

null

sinon.stub(Database, 'connect').returns(Promise.reject( Error('oops') ))

null

require('sinon-as-promised');
sinon.stub(Database, 'connect').rejects(Error('oops'));

null

参见http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections

匿名用户

Mocha中的断言库通过在断言不正确的情况下抛出错误来工作。抛出错误会导致拒绝的承诺,即使在提供给方法的executor函数中抛出也是如此。

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

在上面的代码中,被对象的求值为,因此断言库抛出一个错误。永远不会被抓到。错误的结果是永远不会调用方法。Mocha的回调接受这些错误,因此您可以简单地用结束Mocha中的所有承诺链。这样可以确保始终调用done方法,并以与Mocha在同步代码中捕获断言错误时相同的方式报告错误。

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');
  })).then(done,done);
});

在Mocha中测试承诺时使用。then(DoneDone)的想法值得称赞。