用 Chai 处理 promise 拒绝
Posted
技术标签:
【中文标题】用 Chai 处理 promise 拒绝【英文标题】:Handle promise rejection with Chai 【发布时间】:2018-08-26 08:50:03 【问题描述】:我有以下验证功能检查用户是否存在:
validate.user = async (user, password) =>
const matches = await bcrypt.compare(password, user.password);
if (matches) return user;
if (!matches)
return validate.logAndThrow('User password does not match');
return validate.logAndThrow('Error in bcrypt compare');
;
以下使用 Chai 的测试应该对此进行测试:
chai.use(sinonChai);
const expect = chai;
describe('#user', () =>
it('show throw if user is undefined', () =>
expect(() => validate.user(undefined, 'pass')).to.throw('User does not exist');
);
确实会引发错误,但是 mocha 在控制台中显示以下内容:
2) 如果用户未定义,则显示抛出 (节点:18587)UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝 id:2):错误:用户不存在
所以我的问题是,我如何重写测试以使其确实捕获承诺拒绝?
【问题讨论】:
【参考方案1】:要测试基于 Promise 的函数(异步),请使用 chai-as-promised 插件:
expect(validate.user(undefined, 'pass')).to.be.rejectedWith(Error, 'User does not exist');
在这种情况下,您不要将() => validate.user()
放入expect
,因为它不会返回承诺。 async
函数总是返回一个承诺,因此只需在 expect
中调用您的方法就足够了(无需将其包装到方法中)。
我希望这很清楚 :) 如果您有任何问题 - 请随时提问。
【讨论】:
这似乎是正确的解决方案。不再有警告,但也没有绿色复选标记,只是“2)如果用户未定义则显示抛出”红色没有描述。 请稍等,我会检查一下这个问题。 难道上面应该是“should.be.rejectedWith(Error, 'Message')?但仍然没有绿色的标记。【参考方案2】:我不完全确定是 mocha 会引发未处理的拒绝。
我认为是您的 bcrypt.compare 本质上是异步的并使用回调。 await
不能真正开箱即用地与异步函数一起使用。
但您可以使用节点 util
库来承诺异步调用,如下所示:
const util = require('util');
const bcrypt = require('bcrypt');
const bcryptCompare = util.promisify(bcrypt.compare);
现在您可以按照您的意愿使用await bcryptCompare(password, user.password);
。请注意,我在 await 调用后更改了常量。
还要使用async/await
处理拒绝,您应该像这样使用try/catch
:
let matches;
try
matches = await bcryptCompare(password, user.password);
catch(bcryptError)
throw new Error(bcryptError);
【讨论】:
谢谢,这是有道理的。但是在 catch 块中有一个错字:bcryptError。但是,由于我仍然收到 UnhandledPromiseRejectionWarning,我认为这不能解决问题。以上是关于用 Chai 处理 promise 拒绝的主要内容,如果未能解决你的问题,请参考以下文章
在Angular 2中拒绝Promise时未处理的Promise拒绝[重复]
promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解