Gunakan metode NUnit Assert.Throws atau atribut ExpectedException?


146

Saya telah menemukan bahwa ini tampaknya menjadi dua cara utama untuk menguji pengecualian:

Assert.Throws<Exception>(()=>MethodThatThrows());

[ExpectedException(typeof(Exception))]

Manakah dari ini yang terbaik? Apakah satu menawarkan keunggulan dibandingkan yang lain? Atau itu hanya masalah preferensi pribadi?


3
Pilihan ketiga adalah gaya fasih:Assert.That(() => MethodThatThrows(), Throws.Exception)
Jack Ukleja

1
NUnit versi 3 dan yang lebih baru tidak lagi mendukung ExpectedExceptionatribut tersebut, jadi untuk versi 3+ hanya Assert.Throwsvarian yang relevan.
joanlofe

Kenapa gitu? Nunit3 itu memutuskan untuk menghentikan dukungan itu? Apakah googling sekitar dan tidak dapat menemukan penjelasan untuk itu ... JUnit masih mendukung cara ini, bukan?
ahaaman

Jawaban:


92

Yang pertama memungkinkan Anda menguji lebih dari satu pengecualian, dengan beberapa panggilan:

Assert.Throws(()=>MethodThatThrows());
Assert.Throws(()=>Method2ThatThrows());

Yang kedua hanya memungkinkan Anda untuk menguji satu pengecualian per fungsi tes.


25
Tes seharusnya hanya menguji satu bit logika yang berbeda, jadi bukankah menguji dua kesalahan dalam unit test yang sama dianggap praktik yang buruk?
SamuelDavis

5
@SamuelDavis - secara umum Anda tidak ingin menguji berbagai kasus dalam tes yang sama. Namun, mungkin ada beberapa use case untuk banyak Assert.Throws.
chue x

3
Either way, di sini Anda mendapatkan pengecualian sebagai parameter, yang memungkinkan Anda untuk menegaskan detail dalam pengecualian. Selain itu, menggunakan "Pengecualian yang diharapkan" tidak melindungi Anda untuk jenis pengecualian yang sama yang dilemparkan ke pemanggilan metode lain. Di sini, Anda menargetkan metode yang tepat dan bukan keseluruhan tes. Meskipun tes Anda harus memanggil kode yang sangat sedikit, Anda tidak pernah terlalu aman. Terutama ketika kode menjadi kompleks dan / atau pengecualian terlalu umum. Hal-hal seperti "ArgumentNullExceptions" dapat dilemparkan banyak dan misalnya akan mudah terjawab menggunakan ExpectedException. Tegas. Throws tidak akan melewatkannya.
Gil Sand

254

Perbedaan utama adalah:

ExpectedException()Atribut membuat tes lulus jika pengecualian terjadi di setiap tempat dalam metode pengujian
Penggunaan Assert.Throws()memungkinkan untuk menentukanexact tempat kode di mana pengecualian diharapkan.

NUnit 3.0 menjatuhkan dukungan resmi untuk ExpectedException semuanya.

Jadi, saya pasti lebih suka menggunakan Assert.Throws()metode daripada ExpectedException()atribut.


7
Sejauh ini, inilah jawaban yang benar. Secara kebetulan, Assert.Throws () juga mengembalikan pengecualian, yang dapat memungkinkan pemeriksaan tambahan atas properti pengecualian, jika itu penting bagi Anda.
perfeksionis

1
Akhirnya jawablah mengapa saya tidak bisa membuat ExpectedException berfungsi .. dengan versi 3.
2017

2
Berikut ini tautan github.com/nunit/docs/wiki/Breaking-Changes - ExpectedExceptionAttribute tidak lagi didukung.
Anton Lyhin

Untuk mengubahnya agar berfungsi di bawah NUnit 3.0, ubah sebagai berikut
Andrei Krasutski

38

Saya lebih suka assert.throws karena memungkinkan saya untuk memverifikasi dan menegaskan kondisi lain setelah pengecualian dilemparkan.

    [Test]
    [Category("Slow")]
    public void IsValidLogFileName_nullFileName_ThrowsExcpetion()
    {
        // the exception we expect thrown from the IsValidFileName method
        var ex = Assert.Throws<ArgumentNullException>(() => a.IsValidLogFileName(""));

        // now we can test the exception itself
        Assert.That(ex.Message == "Blah");

    }

Ini adalah salah satu jawaban yang lebih baik, cukup umum bahwa Anda ingin memverifikasi bahwa sesuatu telah memasuki kondisi yang salah setelah pengecualian dilemparkan.
Rhys Bevilaqua

11

Anda juga dapat dengan kuat mengetik kesalahan yang Anda harapkan (seperti versi attrib yang lama).

Assert.Throws<System.InvalidOperationException>(() => breakingAction())

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.