Używam kilku różnych wzorów. Używam ExpectedException
atrybutu przez większość czasu, gdy oczekiwany jest wyjątek. To wystarcza w większości przypadków, jednak w niektórych przypadkach jest to niewystarczające. Wyjątek może nie być możliwy do złapania - ponieważ jest wyrzucany przez metodę, która jest wywoływana przez odbicie - lub może po prostu chcę sprawdzić, czy inne warunki są utrzymane, powiedzmy, że transakcja została wycofana lub jakaś wartość jest nadal ustawiona. W takich przypadkach zawijam go w try/catch
blok, który oczekuje dokładnego wyjątku, wykonuje polecenie, Assert.Fail
jeśli kod się powiedzie, a także przechwytuje ogólne wyjątki, aby upewnić się, że nie zostanie zgłoszony inny wyjątek.
Pierwszy przypadek:
[TestMethod]
[ExpectedException(typeof(ArgumentNullException))]
public void MethodTest()
{
var obj = new ClassRequiringNonNullParameter( null );
}
Drugi przypadek:
[TestMethod]
public void MethodTest()
{
try
{
var obj = new ClassRequiringNonNullParameter( null );
Assert.Fail("An exception should have been thrown");
}
catch (ArgumentNullException ae)
{
Assert.AreEqual( "Parameter cannot be null or empty.", ae.Message );
}
catch (Exception e)
{
Assert.Fail(
string.Format( "Unexpected exception of type {0} caught: {1}",
e.GetType(), e.Message )
);
}
}
Assert.Throws
metodę, która obejmuje oba te przypadki.Teraz, 2017, możesz to zrobić łatwiej dzięki nowej platformie MSTest V2 Framework :
źródło
System.Exception
zostanie wyrzucony. Każdy inny, na przykładSystem.ArgumentException
, nie zda testu.Assert.ThrowsException<MyException>
will testuje wyłącznie podany typ wyjątku, a nie żaden z jego pochodnych typów wyjątków. W naszym przykładzie, jeśli badanaSub
byłaThrow
wMyInheritedException
(typu pochodnych z klasy podstawowegoMyException
), po czym badanie to nie .Try { SubToTest(); Assert.Fail("...") } Catch (AssertFailedException e) {throw;} Catch (MyException e) {...}
. Zwróć uwagę na najważniejsze znaczenieCatch (AssertFailedException e) {throw;}
(por. Komentarz od allgeek)Jestem tu nowy i nie mam reputacji, by komentować lub głosować przeciw, ale chciałem zwrócić uwagę na błąd w przykładzie w odpowiedzi Andy'ego White'a :
We wszystkich znanych mi platformach testowania jednostkowego
Assert.Fail
działa poprzez zgłaszanie wyjątku, więc ogólny catch faktycznie maskuje niepowodzenie testu. JeśliSomethingThatCausesAnException()
nie rzuca,Assert.Fail
wola, ale to nigdy nie wypłynie do biegacza testowego, aby wskazać niepowodzenie.Jeśli chcesz przechwycić oczekiwany wyjątek (tj. Potwierdzić pewne szczegóły, takie jak komunikat / właściwości wyjątku), ważne jest, aby przechwycić określony oczekiwany typ, a nie podstawową klasę wyjątku. Pozwoliłoby to
Assert.Fail
na wypłynięcie wyjątku (zakładając, że nie wyrzucasz tego samego typu wyjątku, co struktura testów jednostkowych), ale nadal zezwala na walidację wyjątku, który został zgłoszony przez TwojąSomethingThatCausesAnException()
metodę.źródło
Od wersji 2.5 NUnit ma następujące poziomy metod
Assert
testowania wyjątków:Assert.Throws , który przetestuje dokładny typ wyjątku:
I
Assert.Catch
, który będzie testować pod kątem wyjątku danego typu lub typu wyjątku pochodzącego z tego typu:Tak na marginesie, podczas debugowania testów jednostkowych, które generują wyjątki, może chcesz zapobiec VS od zerwania na wyjątek .
Edytować
Żeby podać przykład komentarza Mateusza poniżej, powrót ogólnego
Assert.Throws
iAssert.Catch
jest wyjątkiem z rodzajem wyjątku, który możesz następnie zbadać do dalszej analizy:źródło
Assert.Throws
, że dodatkowo zwraca wyjątek, więc możesz pisać dalsze potwierdzenia na samym wyjątku.Niestety MSTest STILL tak naprawdę ma tylko atrybut ExpectedException (pokazuje, jak bardzo MS dba o MSTest), który IMO jest dość okropny, ponieważ łamie wzorzec Arrange / Act / Assert i nie pozwala dokładnie określić, której linii kodu oczekujesz wyjątku występować na.
Kiedy używam (/ zmuszony przez klienta) do używania MSTest, zawsze używam tej klasy pomocniczej:
Przykład użycia:
źródło
Zamiast używać
ExpectedException
atrybutu, czasami definiuję dwie pomocne metody dla moich klas testowych:AssertThrowsException()
przyjmuje delegata i potwierdza, że zgłasza oczekiwany wyjątek z oczekiwanym komunikatem.AssertDoesNotThrowException()
przyjmuje tego samego delegata i zapewnia, że nie zgłasza wyjątku.To parowanie może być bardzo przydatne, gdy chcesz sprawdzić, czy wyjątek jest zgłaszany w jednym przypadku, ale nie w drugim.
Używając ich, mój kod testu jednostkowego może wyglądać następująco:
Ładnie i schludnie, co?
My
AssertThrowsException()
iAssertDoesNotThrowException()
metody są zdefiniowane we wspólnej klasie bazowej w następujący sposób:źródło
W większości frameworków do testów jednostkowych .net można umieścić atrybut [ExpectedException] w metodzie testowej. Jednak nie może to powiedzieć, że wyjątek wystąpił w momencie, w którym się tego spodziewałeś. To miejsce, gdzie xunit.net może pomóc.
Dzięki xunit masz Assert.Throws, więc możesz robić takie rzeczy:
[Fakt] to xunit odpowiednik [TestMethod]
źródło
Oznacz test ExpectedExceptionAttribute (jest to termin w NUnit lub MSTest; użytkownicy innych frameworków do testów jednostkowych mogą wymagać tłumaczenia).
źródło
Zaproponuj użycie czystej składni delegata NUnit .
Przykład testowania
ArgumentNullExeption
:źródło