所以,我正在测试一个依赖于事件 Launcher 的组件 . 为此,我想出了一个使用Promise with 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:Promise error'
(node:25754)UnhandledPromiseRejectionWarning:未处理的promise拒绝(拒绝id:2):AssertionError:Promise错误:expect {Object(message,showDiff,...)}是假的1)应该转换为正确的事件
然后,在2秒后我得到了
错误:超出2000毫秒的超时 . 确保在此测试中调用done()回调 .
自从执行catch回调以来,这甚至更奇怪 . (我认为由于某种原因,断言失败阻止了其余的执行)
现在有趣的是,如果我注释掉 assert.isNotOk(error...)
,测试运行正常,没有控制台中的任何警告 . 它仍然是'fails',因为它执行了捕获 .
但是,我仍然无法理解这些错误 . 有人可以开导我吗?
6 回答
问题是由此造成的:
如果断言失败,则会抛出错误 . 此错误将导致
done()
永远不会被调用,因为代码在它之前出错了 . 这就是造成超时的原因 ."Unhandled promise rejection"也是由失败的断言引起的,因为如果在
catch()
处理程序中抛出错误,并且没有后续的catch()
处理程序,则会吞下错误(如this article中所述) .UnhandledPromiseRejectionWarning
警告提醒您注意这一事实 .一般来说,如果你想在Mocha中测试基于promise的代码,你应该依赖Mocha本身已经可以处理promise的事实 . 您不应该使用
done()
,而是从测试中返回一个承诺 . 然后摩卡会捕捉到任何错误 .像这样:
当与sinon衔接时我得到了这个错误 .
解决方法是在解析或拒绝带存根的promises时使用npm package sinon-as-promised .
代替 ...
使用 ...
还有一种解决方法(注意结尾处的s) .
见http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections
如果断言不正确,Mocha中的断言库通过抛出错误来工作 . 抛出错误会导致拒绝的承诺,即使在提供给
catch
方法的执行程序函数中抛出也是如此 .在上面的代码中,
error
objected的计算结果为true
,因此断言库会抛出一个错误...它永远不会被捕获 . 由于错误,done
方法永远不会被调用 . Mocha的done
回调接受这些错误,因此您可以使用.then(done,done)
简单地结束Mocha中的所有承诺链 . 这确保始终调用done方法,并且报告错误的方式与Mocha捕获同步代码中的断言错误的方式相同 .我赞扬this article在mocha中测试promise时使用.then(done,done)的想法 .
对于那些在测试环境之外寻找错误/警告
UnhandledPromiseRejectionWarning
的人来说,可能是因为代码中的任何人都没有处理承诺中的最终错误:例如,此代码将显示此问题中报告的警告:
(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!
并添加
.catch()
或处理错误应解决警告/错误或者使用
then
函数中的第二个参数这是我对E7 async / await的体验:
如果您从测试中调用了
async helperFunction()
...(我的意思是ES7async
关键字的一个明确的)→确保,你称之为
await helperFunction(whateverParams)
(嗯,是的,当然,一旦你知道......)为了实现这一目标(避免'await是一个保留字'),您的测试函数必须具有外部异步标记:
我遇到了这个问题:
这是我的错误,我正在
then(function(res)
中替换res
对象,所以将res
更改为结果,现在它正在工作 .错了
更正
服务代码: