2013-08-14 12 views
7

Mam obiekt w wyniku wywołania interfejsu API i chcę potwierdzić wartości zmiennej składowej.Czy warto przechwytywać AssertionError w testach JUnit?

Ta wartość może być jedną z dwóch oczekiwanych wartości w zależności od tego, co wywołanie API "widzi" jako pierwsze i które zostanie ustawione jako pierwsze. Więc jeśli asercja na jednej wartości nie powiedzie się, chcę zadeklarować inną wartość przed deklaracją testu jako niepowodzenia.

Jaki jest najlepszy sposób na zrobienie tego? Co mam teraz to:

try { 
    assertEquals("message", someObject.getValue1(), expectedValue1); 
} catch(AssertionError ae) { 
    assertEquals("message", someObject.getValue1(), expectedValue2); 
} 

Po prostu nie jestem pewien, czy jest to dopuszczalna praktyka. Proszę skomentuj.

Odpowiedz

7

Używanie wyjątków jako swego rodzaju gloryfikowanego wyrażenia goto zazwyczaj nie jest dobrą praktyką. Lub przynajmniej wpadniesz na ludzi w swojej karierze, którzy nie zwracają uwagi na używanie wyjątków do kontroli przepływu programu.

Jak o:

Assert.assertTrue((someObject.getValue1().equals(expectedValue1) || (someObject.getValue2().equals(expectedValue2)); 
+0

Dzięki, @Aquilon! W tym przypadku moje twierdzenia są pochowane w metodzie weryfikacji, która przyjmuje za parametry właściwości obiektu, na które muszę się powoływać. Tak naprawdę nie mogę przekazać dwóch oczekiwanych wartości dla tej samej właściwości bez zmiany sygnatury metody. Tak więc trzymam się pierwotnej próby ... łapię rozwiązanie, jednocześnie zauważając twoje rozwiązanie na przyszłość. – Shine

1

ja zgadzam się z Aquilon dotyczące tego nie będącego dobrą praktyką.

Można jednak użyć szyderstwa lub innego mechanizmu, aby "zmusić" API "zobaczyć" jedną pozycję przed drugą? W ten sposób twoje testy mogą odzwierciedlać warunki, które prowadzą do jednego stwierdzenia jest prawdą w jednym teście, a inne twierdzenie jest prawdziwe w innym teście.

5

Zależy od celu, zautomatyzowanych testów funkcjonalnych lub testów jednostkowych. I czasami to zrobić dla byłej:

try { 
    assertTrue(boolean condition from earlier in test method to check); 
} 
catch(AssertionError uhOh) { 
    Logger.err("condition X failed: detailed info msg"); // broken item #1 

} 

try { 
    assertTrue(another condition in same method to check); 
} 
catch(AssertionError yuck) { 
    Logger.err("condition X failed: detailed info msg"); // another broken item 
    fail(); // now blow up as we've checked everything 
} 

Oczywiście, że używa logback Logger i JUnit za Assert.fail(), która zawiedzie metody badawczej. W ten sposób znam wszystkie awarie tej metody, zamiast wysadzać w powietrze po pierwszym. W moim przypadku testuję aplikację internetową z bogatą zawartością (okna dialogowe i strony wymagające dużego wkładu użytkownika).

Wadą "fail-fast" (bez użycia pułapek) jest znalezienie jednego problemu, naprawienie go, ponowne uruchomienie i znalezienie nowego ("płukanie i powtórzenie"), ale jeśli jest używany do testowania jednostkowego, jest to należny składnik aktywów do modułowości testów (najlepiej testujesz tylko jeden aspekt przedmiotu na test).