用 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.all

es6 promise.all()

JS ~ Promise.reject()

promise 的基本概念 和如何解决js中的异步编程问题 对 promis 的 then all ctch 的分析 和 await async 的理解

等待但从未解决/拒绝承诺内存使用[重复]