【问题标题】:Usage of async/await in Mocha - test hangs or ends up with unhandled promise rejection在 Mocha 中使用 async/await - 测试挂起或以未处理的承诺拒绝而告终
【发布时间】:2018-09-16 12:39:34
【问题描述】:

运行非常简单的测试,我在基本授权标头中传递了无效凭据,并且我希望服务器返回 401

const request = require('request-promise');
const expect = require('chai').expect;
const basicToken = require('basic-auth-token');

describe('PUT Endpoint', function () {
 it.only('should return unauthorized if basic token is incorrect', async function (done) {
                let options = {
                    url: `http://url_to_handle_request`,
                    resolveWithFullResponse: true,
                    headers: {
                        Authorization: `Basic ${basicToken('INVALID', 'CREDENTIALS')}`
                    }
                };

                try {
                    await request.put(options); // this should throw exception
                } catch (err) {
                    expect(err.statusCode).to.be.equal(401); // this is called
                }
                done();
            });
});

此代码的问题是 expect 子句解析为 false(因为服务器响应例如 403)并且测试以错误结束:

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): AssertionError: expected 403 to equal 401

如果我省略 done 回调,测试将挂起(名称为红色)并且显然正在“等待”某些事情完成

我知道如果我将它重写为使用标准的 Promise 方法,它会起作用。我只是好奇如何通过 async/await 来实现。

谢谢

【问题讨论】:

    标签: javascript node.js unit-testing mocha.js chai


    【解决方案1】:

    从参数(以及函数体)中删除 done,然后 Mocha 将期望您返回 Promise。

    异步函数默认返回 Promise。

    如果你不抛出错误,它会返回已解决的承诺。

    【讨论】:

    • 谢谢。以前我以这种方式实现了它,但我看不出有什么区别。所以我深入研究了代码并意识到这是 after 函数造成的。所以我对 async 和 after 进行了更正,它开始工作了
    • 如果一个承诺拒绝没有被处理也没有抛出一个错误,它被称为“假”状态。请阅读这篇文章 - ravichandranjv.blogspot.in/2018/03/… - 以获得有关承诺的完整解释。没有支持代码的答案并不是真正的答案。请为您的答案发布支持代码,
    • @user2347763 - 抱歉,这不正确。在异步函数中抛出错误会导致返回被拒绝的 Promise,这会导致正确解除测试并显示正确的错误消息。当您不将done 变量放入测试时,它将期望返回承诺(异步函数总是这样做)而不是调用回调。
    • @libik - 请查看博客文章以获得更详细的代码解释。如果您说必须调用 done 因为异步函数提供了回调,那么这完全是一个不同的问题。您关于“如果您不抛出错误,它返回已解决的承诺”的说法并不完全正确,因为当返回空承诺时,承诺具有虚假状态,而您的陈述实际上是您所说的已解决承诺的虚假状态。
    • @user2347763 - 抱歉,该博客文章与 OP 问题无关,并且本身并没有说太多,而且质量很低。对于 mocha 测试,没有像 falsey 那样的状态,您只能解决或拒绝承诺(如果您省略回调)。返回已解决的空承诺(具有 null 或未定义)是 void 函数的标准方式。
    【解决方案2】:

    更改此代码块

    try {
                        await request.put(options); // this should throw exception
                    } catch (err) {
                        expect(err.statusCode).to.be.equal(401); // this is called
                    }
                    done();
    

                    await request.put(options)
                        .then(()=>{ })
                        .catch(function (err)){ 
                          expect(err.statusCode).to.be.equal(401);
                         }
    

    【讨论】:

    • 这确实不能正常工作,如果抛出错误,done 永远不会被调用
    • @libik - 你知道什么是 promises 以及什么时候调用 done 吗?对于未解决的承诺拒绝,异常警告清楚地表明它将终止该过程,所以如果抛出错误,您的意思是永远不会调用 done? .catch 块有助于处理未解决的承诺拒绝。
    • 你有 .catch ,这意味着它不是未解决的承诺。如果 request.put 抛出错误,它会跳转到 catch(不使用 then ->),使用 expect,如果它通过,它将等待 2 秒,然后,它会以超时(或更多秒,如果你设置 global超时到不同的值)
    • 如果测试通过,即期望 403 而不是 401,则程序 (mocha) 优雅退出。
    • 其实不是,抱歉。如果有错误,则不会调用.then(() => done())。假设expect(401) 对预期的err.statusCode 是正确的,那么它会通过并等待done(),它永远不会被调用并且它以错误结束 - 超时
    猜你喜欢
    • 1970-01-01
    • 2018-09-14
    • 2018-09-28
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 2019-08-27
    • 2017-07-16
    • 2020-01-01
    相关资源
    最近更新 更多