34

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

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

它(显然?)不起作用,因为函数在 Promise 解决之前退出。然而,我发现了这个问题,使用回调可以达到同样的效果。

有什么建议吗?

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

4

5 回答 5

46

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

在异步测试用例中。

于 2016-03-03T20:49:17.920 回答
21

基于Bergi的回答,我建议使用原始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/);
});
于 2017-10-26T14:50:35.540 回答
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'))
}
于 2018-02-01T22:11:45.653 回答
3

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

节点 v10+

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

对于旧版本的 Node

来自vitalets的回答

import assert from 'assert';

async function assertThrowsAsync(fn, regExp) {
  let f = () => {};
  try {
    await fn();
  } catch(e) {
    f = () => {throw e};
  } finally {
    assert.throws(f, regExp);
  }
}
于 2019-03-22T09:41:52.357 回答
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/
            });

        });
于 2018-09-21T19:38:57.820 回答