Node.js断言与异步函数(Promises)

时间:2016-03-03 20:32:54

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

我想检查异步函数是否从本机assert模块使用assert.throws引发。 我试过

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

它(obvioulsy?)不起作用,因为函数在Promise解析之前退出。 然而我发现这个question使用回调来获得相同的东西。

有什么建议吗?

(我正在使用Babel转发到Node.js原生生成器)

5 个答案:

答案 0 :(得分:20)

节点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);

在异步测试用例中

答案 1 :(得分:19)

基于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/);
});

答案 2 :(得分: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'))
}

答案 3 :(得分:0)

您将要使用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/
            });

        });

答案 4 :(得分:0)

由于这个问题仍在引起人们的注意,我想总结两个最佳解决方案,尤其是强调新的标准方法。

节点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);
  }
}