Jest: async / awaittoThrowが機能していません

作成日 2016年09月15日  ·  21コメント  ·  ソース: facebook/jest

次のテスト

async function check() {
  throw new Error('Test');
}

expect(async () => 
  await check()
).toThrow();

失敗し、エラーを適切にキャッチしません(私は最新バージョンのjestを使用しています)

最も参考になるコメント

それ以外の

expect(async () => await check()).toThrow()
// Jest error: "Expected the function to throw an error. But it didn't throw anything."

これは機能します:

expect(check()).rejects.toEqual(new Error('Test'))

ええ、構文は厄介です...

全てのコメント21件

はい、これは現在サポートされていません。 https://github.com/facebook/jest/issues/1377を参照して

それ以外の

expect(async () => await check()).toThrow()
// Jest error: "Expected the function to throw an error. But it didn't throw anything."

これは機能します:

expect(check()).rejects.toEqual(new Error('Test'))

ええ、構文は厄介です...

次のように書くこともできます。

let error;
try {
  await check();
} catch (e) {
  error = e;
}
expect(error).toEqual(new Error('Test'));

以下は私にも役立ちました:

async function check() {
  throw new Error('Test');
}

expect(check()).rejects.toEqual(new Error('Test'))

参照: https

回避策のリストに追加します。
あなたが私のように特定のエラータイプをキャッチしたい、そしてメッセージを気にしないなら:

async function check() {
  throw new SomeSpecificError('Whatever');
}

await check()
  .then(() => {
    throw new Error('Should go to .catch, not enter .then');
  })
  .catch((err) => {
    expect(err).toBeInstanceOf(SomeSpecificError);
  });
await expect(check).rejects.toThrow(SomeSpecificError);

同様に機能するはずです

await expect(check).rejects.toThrow(/DUPLICATES_DETECTED/);

私がしていることです。

async function check() {
  throw new Error("Test");
}
await expect(check).rejects.toThrow(Error);
expect(received).rejects.toThrow()

received value must be a Promise.
Received:
 function: [Function check]

あなたはそれに実際の約束を与えるためにそれを呼び出す必要があります

async function check() {
  throw new Error("Test");
}
await expect(check()).rejects.toThrow(Error);

同様に機能するはずです

it(`some test`, async () => {
  async function check() {
    try {
      return Promise.reject(await asyncMethod());
    } catch (error) {
      throw new Error("test");
    }
  }
  await expect(check()).rejects.toThrow(Error);
});

働ける

バージョン

  • 冗談: 23.4.2
  • ts-jest: 23.1.2

私はそれが約束を必要とすることを知っています、しかしあなたが提供しているケースはそうではありません:)

やあ ! 私は何か間違ったことをしているかもしれませんが、それでも非同期呼び出しのカスタムエラーに問題があります。 次のことを考慮してください。

class CustomErrorType {}
// ...
test('check throws custom error', async () => {            
    async function check() {
        throw new CustomErrorType();
    }
    await expect(check()).rejects.toThrow(CustomErrorType);
});

その後、テストは次の出力で失敗します。

関数が次のタイプのエラーをスローすることが期待されていました:
「CustomErrorType」
しかし、それは何も投げませんでした。

したがって、テストは失敗します-スローされたクラスがError場合、テストは完全に機能します。 Errorを拡張しようとすると
`` `javascript
クラスCustomErrorTypeはエラー{}を拡張します
「」

その場合、エラーは

関数が次のタイプのエラーをスローすることが期待されていました:
「CustomErrorType」
代わりに、それは投げました:
エラー

そのサンプルの何が問題なのかについての手がかりはありますか? 私はjest23.4.2を使用しています。

@Marchelune class CustomErrorType extends Error {}を書くとき、実際には新しいクラスを定義していません。 CustomErrorTypeに本体を指定すると、super()を呼び出すだけのコンストラクターであっても、機能します。

誰かがインスタンスのErrorクラスとは異なるものをスローし、そのスレッドからのアドバイスを使用するのに苦労した場合(私がしたように)。
toThrow()は、スローされた値がErrorクラスのインスタンスであるかどうかを確認し、そうでない場合は、throwは検出されません。 これは、ドキュメントと常識からは明らかではありませんでした。
明らかに次のようにスローされますが、これは失敗します。

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toThrow()`

しかし、これは機能します(より良い方法があるかどうかはわかりません):

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toBeTruthy()`

@KaraburのタイプミスtoBeThruthytoBeTruthy必要があります

これは、スローせずに特定のエラーに一致した場合に確実に破損することを保証する明示的なテストです。

yourCoolAsyncMethod('yeah it is')
    .then(ok => { // Presumes not a Promise<void>
        expect(ok).toBeUndefined();
        done();
    })
    .catch(bad => {
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

こんにちは@SimenB。
私がこれを持っていて、それが機能している場合。

async function check() {
    // do something
}
await expect(check()).rejects.toThrow(InternalServerErrorException);

InternalServerErrorExceptionがオブジェクトとともにスローされます...。

スローされたエラーのプロパティについてもアサートするにはどうすればよいですか? 例えば:

  • exception.message = 'エラー'
  • exception.status = '500'

これは、スローせずに特定のエラーに一致した場合に確実に破損することを保証する明示的なテストです。

yourCoolAsyncMethod('yeah it is')
    .then(ok => {
        expect(ok).toBeUndefined();
        done();
    })
    .catch(bad => {
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

これに関する問題は、コードにエラーがない場合、テストに合格することです。

したがって、このテストは、テストするコードにエラーがあるかどうかによって期待される結果が異なるため、実際にはあまり価値がありません。

テストには負のフローまたは正のフローが必要であり、テストに必要なものだけをテストする必要があります。 この種のランダム性は最大ではありません。

ねえ@David-Tennant🖐

それを指摘してくれてありがとう。 当時、私はPromise<notVoid>メソッドに取り組んでいました。 Promise<void>も有効な共通のソリューションを共有していないことに気づきました。 私は自分の答えを、私が仮定をしたというコメントで更新しました。 流れについては同意します。

ありがとう💨

ハウディ@ futuredayv👋

ねえ@David-Tennant🖐

それを指摘してくれてありがとう。 当時、私はPromise<notVoid>メソッドに取り組んでいました。 Promise<void>も有効な共通のソリューションを共有していないことに気づきました。 私は自分の答えを、私が仮定をしたというコメントで更新しました。 流れについては同意します。

ありがとう💨

問題は、テストがvoidを返した場合でも、テストに合格することです。 どちらがバグでしょうか?
done()電話するということは、「私のテストは期待どおりに合格し、次のテストに進む準備ができている」という意味です。

yourCoolAsyncMethod('yeah it is')
     // -- Lets say your method does not throw, and returns void instead
    .then(ok => { // Presumes not a Promise<void>
        expect(ok).toBeUndefined(); // -- At this point if it was void, this would pass
        done(); // -- Then your test would end and the catch would not be reached
        // -- Now you have unknown behavior passing a test where it's suppose to catch a fail
    })
    .catch(bad => {
        // -- This block does not run because done() is called above
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

ユースケースの解決策がわからない。 しかし、私はthen done()を呼び出さないことから始めるか、テストが失敗することを確認するために「then」でエラーをスローすることから始めます。

yourCoolAsyncMethod('yeah it is')
    .then(ok => throw new Error("This block of code should not be reached")
    .catch(bad => {
        expect(bad).toBeDefined();
        expect(bad).toMatchInlineSnapshot(
            `Specifically serious error!`
        );

        done();
    });

誰かがインスタンスのErrorクラスとは異なるものをスローし、そのスレッドからのアドバイスを使用するのに苦労した場合(私がしたように)。
toThrow()は、スローされた値がErrorクラスのインスタンスであるかどうかを確認し、そうでない場合は、throwは検出されません。 これは、ドキュメントと常識からは明らかではありませんでした。
明らかに次のようにスローされますが、これは失敗します。

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toThrow()`

しかし、これは機能します(より良い方法があるかどうかはわかりません):

async function f() {throw 'aa'}
const res = await expect(f()).rejects.toBeTruthy()`

もう少し良い方法は、 toBeDefined()代わりにtoBeTruthy() toBeDefined()を使用することです。
async function f() {throw 'aa'} const res = await expect(f()).rejects.toBeTruthy()`

このページは役に立ちましたか?
0 / 5 - 0 評価