Jest: async/menunggu toThrow tidak berfungsi

Dibuat pada 15 Sep 2016  ·  21Komentar  ·  Sumber: facebook/jest

tes berikutnya

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

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

akan gagal dan tidak menangkap kesalahan dengan benar (saya menggunakan versi terbaru dari lelucon)

Komentar yang paling membantu

Dari pada

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

ini bekerja:

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

Ya sintaksnya canggung ...

Semua 21 komentar

Ya, ini tidak didukung saat ini. Lihat https://github.com/facebook/jest/issues/1377

Dari pada

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

ini bekerja:

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

Ya sintaksnya canggung ...

Anda juga dapat menulis:

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

Berikut ini juga berhasil untuk saya:

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

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

Lihat: https://facebook.github.io/jest/docs/en/tutorial-async.html#rejects

Menambahkan ke daftar solusi.
Jika Anda suka saya ingin menangkap jenis kesalahan tertentu, dan tidak peduli dengan pesannya:

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

Harus bekerja juga

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

adalah apa yang saya lakukan.

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]

Anda perlu memintanya untuk memberikan janji yang sebenarnya

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

Harus bekerja juga

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

bisa bekerja

Versi: kapan

  • lelucon: 23.4.2
  • ts-jest: 23.1.2

Saya tahu itu perlu janji, tetapi kasing yang Anda tawarkan tidak :)

Hai ! Saya mungkin melakukan sesuatu yang salah, tetapi saya masih memiliki masalah dengan kesalahan khusus dalam panggilan asinkron. Pertimbangkan hal berikut:

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

maka tes gagal dengan output berikut:

Diharapkan fungsi melempar kesalahan tipe:
"Tipe Kesalahan Kustom"
Tapi itu tidak membuang apa pun.

Jadi tes gagal - sementara itu berfungsi dengan baik ketika kelas yang dilemparkan adalah Error . Ketika saya mencoba untuk memperpanjang Error dengan
```javascript
kelas CustomErrorType memperluas Kesalahan {}
````

maka kesalahannya adalah

Diharapkan fungsi melempar kesalahan tipe:
"Tipe Kesalahan Kustom"
Sebaliknya, itu melemparkan:
Kesalahan

Adakah petunjuk tentang sesuatu yang salah dalam sampel itu? Saya menggunakan lelucon 23.4.2.

@Marchelune Ketika Anda menulis class CustomErrorType extends Error {} Anda belum benar-benar mendefinisikan kelas baru. Jika Anda memberi CustomErrorType sebuah badan, bahkan hanya sebuah konstruktor yang tidak melakukan apa pun selain memanggil super(), itu akan berfungsi.

Jika seseorang melempar sesuatu yang berbeda dari instance kelas Kesalahan dan berjuang untuk menggunakan saran dari utas itu (seperti yang saya lakukan).
toThrow() akan memeriksa nilai apa yang dilempar adalah turunan dari kelas Kesalahan, dan jika tidak - lemparan tidak akan terdeteksi. Ini tidak jelas dari dokumen dan akal sehat.
Ini akan gagal, meskipun jelas melempar:

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

tetapi ini akan berhasil (tidak yakin apakah ada cara yang lebih baik):

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

@Karabur salah ketik toBeThruthy seharusnya toBeTruthy

Inilah tes eksplisit yang memastikannya pasti akan rusak jika TIDAK melempar dan cocok dengan kesalahan tertentu.

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

Hai @SimenB.
Jika saya memiliki ini dan itu berhasil.

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

InternalServerErrorException dilemparkan dengan objek....

Bagaimana saya bisa juga menegaskan properti pada kesalahan yang dilemparkan? Sebagai contoh:

  • exception.message = 'ERROR'
  • pengecualian.status = '500'

Inilah tes eksplisit yang memastikannya pasti akan rusak jika TIDAK melempar dan cocok dengan kesalahan tertentu.

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

        done();
    });

Masalah tentang ini adalah bahwa pengujian Anda akan lulus jika kode tidak pernah memiliki kesalahan.

Jadi tes ini tidak akan benar-benar menawarkan banyak nilai karena hasil yang diharapkan bervariasi berdasarkan apakah kode yang diuji memiliki kesalahan atau tidak.

Tes harus memiliki aliran negatif atau aliran positif dan kita hanya boleh menguji apa yang diperlukan untuk menguji. Keacakan semacam ini bukanlah yang terbesar.

Hai @David-Tennant

Terima kasih telah menunjukkan itu. Saya sedang mengerjakan metode Promise<notVoid> saat itu. Saya menyadari bahwa saya tidak membagikan solusi umum yang juga berlaku untuk Promise<void> . Saya memperbarui jawaban saya dengan komentar yang mengatakan saya membuat asumsi. Saya setuju dengan Anda tentang alirannya.

Terima kasih

Halo @futuredayv

Hai @David-Tennant

Terima kasih telah menunjukkan itu. Saya sedang mengerjakan metode Promise<notVoid> saat itu. Saya menyadari bahwa saya tidak membagikan solusi umum yang juga berlaku untuk Promise<void> . Saya memperbarui jawaban saya dengan komentar yang mengatakan saya membuat asumsi. Saya setuju dengan Anda tentang alirannya.

Terima kasih

Masalahnya adalah bahwa tes Anda akan tetap lulus jika tes kembali batal. Yang mana yang seharusnya menjadi bug kan?
Memanggil done() berarti "Tes saya telah lulus dengan cara yang diharapkan dan saya siap untuk melanjutkan ke tes berikutnya"

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

Tidak yakin apa solusinya untuk kasus penggunaan Anda. Tapi saya akan mulai dengan tidak memanggil done() di then atau mungkin membuat kesalahan di "then" untuk memastikan tes gagal,

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

Jika seseorang melempar sesuatu yang berbeda dari instance kelas Kesalahan dan berjuang untuk menggunakan saran dari utas itu (seperti yang saya lakukan).
toThrow() akan memeriksa nilai apa yang dilempar adalah turunan dari kelas Kesalahan, dan jika tidak - lemparan tidak akan terdeteksi. Ini tidak jelas dari dokumen dan akal sehat.
Ini akan gagal, meskipun jelas melempar:

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

tetapi ini akan berhasil (tidak yakin apakah ada cara yang lebih baik):

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

Cara yang sedikit lebih baik adalah menggunakan toBeDefined() daripada toBeTruthy() :
async function f() {throw 'aa'} const res = await expect(f()).rejects.toBeTruthy()`

Apakah halaman ini membantu?
0 / 5 - 0 peringkat