Використовувати метод NUnit Assert.Throws або атрибут очікуваного розширення?


146

Я виявив, що, здається, це два основні способи тестування на винятки:

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

[ExpectedException(typeof(Exception))]

Яке з них було б найкращим? Чи пропонує один перевага перед іншим? Або це просто питання особистої переваги?


3
Третій варіант - вільний стиль:Assert.That(() => MethodThatThrows(), Throws.Exception)
— Jack Ukleja

1
Версія 3 і новіша версія NUnit більше не підтримують ExpectedExceptionатрибут, тому для версії 3+ Assert.Throwsактуальний лише варіант.
— joanlofe

Чому так? Що Nunit3 вирішив кинути цю підтримку? Був гугл навколо і не міг знайти пояснення для цього ... JUnit все ще підтримує цей шлях, чи не так?
— ахааман

Відповіді:


92

Перший дозволяє протестувати більш ніж один виняток із кількома викликами:

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

Другий дозволяє перевірити лише один виняток на тестову функцію.


25
Тест повинен перевірити лише один чіткий біт логіки, тож чи не тестування двох помилок в одному і тому ж тесті блоку не вважатиметься поганою практикою?
— SamuelDavis

5
@SamuelDavis - взагалі ви не хочете перевіряти різні випадки в одному тесті. Однак може бути деякий випадок використання для кількох Assert.Throws.
— chue x

3
Так чи інакше, тут ви отримуєте виняток як параметр, який дозволяє стверджувати деталі у винятку. Також використання "Очікуваний виняток" не захищає вас від того ж типу винятку, який буде перекинуто в інший виклик методу. Тут ви орієнтуєтеся на точний метод, а не на весь тест. Хоча ваш тест повинен називати дуже мало коду, ви ніколи не надто безпечні. Особливо, коли код стає складним та / або винятком занадто загальним. Такі речі, як "ArgumentNullExceptions", можуть бути кинуті дуже багато, і, наприклад, їх легко пропустити за допомогою очікуваного Exxception. Assert.Throw не пропустив би це.
— Гіль Санд

254

Основна відмінність:

ExpectedException()атрибут робить тест пройденим, якщо виключення трапляється в будь-якому місці методу тестування.
Використання Assert.Throws()дозволяє вказати exactмісце коду, де очікується виняток.

NUnit 3.0 ExpectedExceptionвзагалі знижує офіційну підтримку .

Отже, я, безумовно, вважаю за краще використовувати Assert.Throws()метод, а не ExpectedException()атрибут.


7
Це, безумовно, правильна відповідь. До речі, Assert.Throws () також повертає виняток, який може дозволити додатковий огляд властивостей винятку, якщо вони мають значення для вас.
— перфекціоніст

1
Нарешті дайте відповідь, чому я не можу
— заставити очікуване розширення

2
Ось посилання github.com/nunit/docs/wiki/Breaking-Changes - очікуванеExceptionAttribute більше не підтримується.
— Антон Лихін


38

Я віддаю перевагу assert.throw, оскільки це дозволяє мені перевіряти та стверджувати інші умови після відкидання виключення.

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

    }

Це одна з кращих відповідей. Досить поширеним є той факт, що ви хочете перевірити, що щось увійшло в помилковий стан після скидання винятку.
— Rhys Bevilaqua

11

Ви також можете сильно ввести помилку, яку ви очікуєте (наприклад, стару версію attrib).

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

1

Якщо ви використовуєте старішу версію ( <= 2.0 ), NUnitтоді вам потрібно скористатися ExpectedException.

Якщо ви використовуєте версію 2.5 або новішої версії, тоді ви можете використовуватиAssert.Throw()

https://github.com/nunit/docs/wiki/Breaking-Changes

Як користуватися: https://www.nunit.org/index.php?p=exceptionAsserts&r=2.5

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.