【问题标题】:Node.js assert.throws with async functions (Promises)Node.js assert.throws 带有异步函数(Promises)
【发布时间】:2016-06-17 09:13:46
【问题描述】:

我想检查是否使用原生 assert 模块中的 assert.throws 引发了异步函数。 我试过了

const test = async () => await aPromise();
assert.throws(test); // AssertionError: Missing expected exception..

它(显然?)不起作用,因为函数在 Promise 解决之前退出。 然而我发现this question 使用回调实现了同样的事情。

有什么建议吗?

(我正在使用 Babel 转换为 Node.js 原生生成器。)

【问题讨论】:

    标签: javascript node.js async-await assert ecmascript-next


    【解决方案1】:

    节点 10 和更新的节点

    从 Node.js v10.0 开始,assert.rejects 就是这样做的。

    旧版本节点

    async 函数从不抛出 - 它们返回可能被拒绝的承诺。

    您不能对它们使用assert.throws你需要自己编写异步断言

    async function assertThrowsAsynchronously(test, error) {
        try {
            await test();
        } catch(e) {
            if (!error || e instanceof error)
                return "everything is fine";
        }
        throw new AssertionError("Missing rejection" + (error ? " with "+error.name : ""));
    }
    

    并像使用它

    return assertThrowsAsynchronously(aPromise);
    

    在异步测试用例中。

    【讨论】:

    • 这是不必要的,因为assert.throws 已经返回了一个行为与此完全相同的承诺
    • @Ali 您在使用哪个assert.throwsnative node.js one 既不返回承诺,也不处理返回承诺的函数
    • 这是原生的。至少在节点 v8 中。它没有记录在案,但这就是它正在做的事情。
    • 是的,它没有。对困惑感到抱歉。我们正在使用来自npmassert-throws-async 并替换本机assert.throws。我错过了它,因为原始文件已替换为不同的文件,并且无需在我的文件中重新导入 assert-throws-async 即可工作。
    【解决方案2】:

    基于Bergi answer,我建议使用原始assert.throws 获取错误消息的更通用的解决方案:

    import assert from 'assert';
    
    async function assertThrowsAsync(fn, regExp) {
      let f = () => {};
      try {
        await fn();
      } catch(e) {
        f = () => {throw e};
      } finally {
        assert.throws(f, regExp);
      }
    }
    

    用法:

    it('should throw', async function () {
        await assertThrowsAsync(async () => await asyncTask(), /Error/);
    });
    

    【讨论】:

    • 优秀的解决方案,希望能成为官方断言库!
    • 你是我的英雄!
    • 是的,不要在 2018 年及以后使用这个,使用 assert.rejects(),这里:nodejs.org/api/…
    【解决方案3】:

    给出的答案有效,但我今天遇到了这个问题并想出了另一个解决方案,我认为它更简单一些。

    // Code being tested
    async function thisFunctionThrows() {
        throw new Error('Bad response')
    }
    
    
    // In your test.
    try {
        await thisFunctionThrows()
        assert.equal(1 == 0) // Never gets run. But if it does you know it didn't throw.
    } catch (e) {
        assert(e.message.includes('Bad response'))
    }
    

    【讨论】:

    • 由于我使用的是较早版本的 Node (
    【解决方案4】:

    由于这个问题仍然受到关注,我想总结两个最佳解决方案,特别是强调新的标准方法。

    节点 v10+

    断言库中有一个专用方法,assert.rejects

    对于旧版本的 Node

    来自vitalets answer的填充:

    import assert from 'assert';
    
    async function assertThrowsAsync(fn, regExp) {
      let f = () => {};
      try {
        await fn();
      } catch(e) {
        f = () => {throw e};
      } finally {
        assert.throws(f, regExp);
      }
    }
    

    【讨论】:

      【解决方案5】:

      您将要使用 assert.rejects(),这是 Node.js 版本 10 中的新功能。

      在高层次上,我们想要的是 assert.rejects 之类的东西,而不是 assert.throws,希望你能接受并运行它:

              const assertRejects = (fn, options) => {
                  return Promise.resolve(fn()).catch(e => {
                          return {
                              exception: e,
                              result: 'OK'
                          }
                      })
                      .then(v => {
      
                          if (!(v && v.result === 'OK')) {
                              return Promise.reject('Missing exception.');
                          }
      
                          if (!options) {
                              return;
                          }
      
                          if (options.message) {
                              // check options
                          }
      
                          console.log('here we check options');
      
                      });
              };
      
              it('should save with error', async () => {
      
                  // should be an error because of duplication of unique document (see indexes in the model)
                  return await assertRejects(async () => {
      
                      patientSubscriber = await PatientSubscriber.create({
                          isSubscribed: true,
                          patient: patient._id,
                          subscriber: user._id
                      });
      
                  }, {
                      message: /PatientSubscriber validation failed/
                  });
      
              });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-11
        • 1970-01-01
        • 1970-01-01
        • 2015-05-24
        • 1970-01-01
        • 2016-01-02
        • 1970-01-01
        • 2016-10-26
        相关资源
        最近更新 更多