簡體   English   中英

Node.js assert.throws 與異步函數(承諾)

[英]Node.js assert.throws with async functions (Promises)

我想檢查異步函數是否使用本機assert模塊中的assert.throws拋出。 我試過

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

它(顯然?)不起作用,因為函數在 Promise 被解析之前退出。 然而,我發現這個問題使用回調實現了同樣的事情。

有什么建議嗎?

(我正在使用 Babel 轉換為 Node.js 原生生成器。)

節點 10 及更新版本

從 Node.js v10.0 開始, assert.rejects就是這樣做的。

舊版本的節點

async函數從不拋出 - 它們返回可能被拒絕的承諾。

您不能將assert.throws與它們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);

在異步測試用例中。

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

給出的答案有效,但我今天遇到了這個問題並提出了另一種解決方案,我認為它更簡單一些。

// 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'))
}

由於這個問題仍然受到關注,我想總結一下兩個最佳解決方案,特別是強調新的標准方法。

節點 v10+

assert 庫中有一個專用方法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);
  }
}

您將要使用 Node.js 版本 10 中的新增功能assert.rejects()

在高層次上,我們想要的是 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/
            });

        });

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM