web-dev-qa-db-ja.com

Node.js assert.throws with async functions(Promises)

ネイティブassertモジュールの assert.throws を使用して非同期関数がスローするかどうかを確認したいと思います。私が試した

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

Promiseが解決される前に関数が終了するため、(obvioulsy?)は機能しません。それでも私はこれを発見しました 質問 コールバックを使用して同じことが達成されます。

なにか提案を?

(私はBabelを使用してNode.jsネイティブジェネレーターに変換しています)

20
mattecapu

質問はまだ注目されているので、特に新しい標準的な方法を強調するために、2つの最良の解決策を要約したいと思います。

ノードv10 +

アサートライブラリには専用のメソッド assert.rejects

古いバージョンのノードの場合

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);
  }
}
1
mattecapu

ノード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);

非同期テストケース

21
Bergi

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/);
});
19
vitalets

答えは上手くいきましたが、私は今日この問題に出くわし、もう少し簡単な解決策を考え出しました。

// 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
jayWHY

Node.jsバージョン10の新機能であるassert.rejects()を使用します。

高レベルでは、assert.throwsの代わりに、assert.rejectsのようなものが必要です。うまくいけば、これを取得して実行できます。

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

        });
0
Alexander Mills