Використовувати метод 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.