所以,我正在测试一个依赖于事件发射器的组件。为此,我想出了一个使用 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, …) } 是假的
- 应该使用正确的事件进行转换
然后,2秒后我得到
错误:超过 2000 毫秒的超时。确保 done() 回调是
在这个测试中被调用。
自从执行了 catch 回调之后,这更奇怪了(我认为由于某种原因,断言失败阻止了其余的执行)
现在有趣的是,如果我注释掉 assert.isNotOk(error...)
测试运行良好,控制台中没有任何警告。在执行捕获的意义上,它仍然“失败”。
但是,我仍然无法用承诺来理解这些错误。有人可以启发我吗?
原文由 Jzop 发布,翻译遵循 CC BY-SA 4.0 许可协议
问题是由此引起的:
如果断言失败,则会抛出错误。这个错误将导致
done()
永远不会被调用,因为代码在它之前出错了。这就是导致超时的原因。“未处理的承诺拒绝” 也是由失败的断言引起的,因为如果在
catch()
处理程序中抛出错误, _并且没有后续的catch()
处理程序_,错误将被吞没(如 本文所述)。UnhandledPromiseRejectionWarning
警告提醒您注意这一事实。一般来说,如果你想在 Mocha 中测试基于 Promise 的代码,你应该依赖 Mocha 本身已经可以处理 Promise 的事实。你不应该使用
done()
,而是从你的测试中返回一个承诺。然后 Mocha 将自己捕获任何错误。像这样: