2013-05-16 22 views
21

Napisałem kilka przypadków testowych, aby przetestować jakąś metodę. Ale niektóre metody rzucają wyjątek. Czy robię to poprawnie?jak obsługiwać wyjątki w junit

private void testNumber(String word, int number) { 
    try { 
     assertEquals(word, service.convert(number)); 
    } catch (OutOfRangeNumberException e) { 
     Assert.fail("Test failed : " + e.getMessage()); 
    } 
} 

@Test 
public final void testZero() { 
    testNumber("zero", 0); 
} 

Jeśli mijam -45, zakończy się niepowodzeniem z OutOfRangeException ale nie jestem w stanie przetestować specyficzny wyjątek jak @Test(Expected...)

Odpowiedz

6

Nie trzeba złapać wyjątek niepowodzenie testu. Po prostu odpuść (deklarując throws), ale i tak to się nie powiedzie.

Innym przypadkiem jest sytuacja, w której rzeczywiście oczekuje się wyjątku, a następnie umieszcza się błąd na końcu bloku try.

Na przykład:

@Test 
public void testInvalidNumber() { 
    try { 
     String dummy = service.convert(-1)); 
     Assert.fail("Fail! Method was expected to throw an exception because negative numbers are not supported.") 
    } catch (OutOfRangeException e) { 
     // expected 
    } 
} 

Można korzystać z tego rodzaju badania w celu sprawdzenia, czy kod jest prawidłowo Weryfikacja danych i obsługuje nieprawidłowe dane z właściwego wyjątku.

+1

ExpectedException jest preferowanym sposobem sprawdzenia dla przewidywanych wyjątków. –

+0

Zgadzam się, a ja już przegłosowałem odpowiedź Erica. – javadeveloper

+0

Potrzebujesz tylko ExpectedException, jeśli chcesz sprawdzić strukturę wyjątku. Na przykład, CmisExceptions powinny mieć określony powód niepowodzenia ustawiony w nich. Musiałem napisać testy, żeby to sprawdzić, i użyłem w tym celu mataczy Hamcrest. Jeśli spodziewasz się wyjątku, użyj argumentu @Test. –

15

Wyjąć blok try-catch i dodać throws Exception do metody badania, jak:

@Test 
public final void testZero() throws Exception { 
    assertEquals("zero", service.convert(0)); 
} 

JUnit oczekuje braku testy rzuci wyjątkami, swój wzrok nich jest właśnie zatrzymanie JUnit od bycia w stanie je zgłosić prawidłowo. W ten sposób będzie działać oczekiwana właściwość w adnotacji @Test.

45

Nieoczekiwany wyjątek jest niepowodzeniem testu, więc użytkownik nie musi ani nie chce go przechwycić.

@Test 
public void canConvertStringsToDecimals() { 
    String str = "1.234"; 
    Assert.assertEquals(1.234, service.convert(str), 1.0e-4); 
} 

Do service nie rzucać IllegalArgumentException ponieważ str ma punkt dziesiętny w nim, że będzie proste niepowodzenie testu.

Oczekiwany wyjątek powinien być obsługiwany przez opcjonalny argument expected z @Test.

@Test(expected=NullPointerException.class) 
public void cannotConvertNulls() { 
    service.convert(null); 
} 

Jeśli programista był leniwy i rzucił Exception, lub gdyby miał service zwrot 0.0, test zakończy się niepowodzeniem. Tylko NPE zakończy się pomyślnie. Należy zauważyć, że podklasy oczekiwanego wyjątku również działają. To rzadkość w przypadku NPE s, ale jest wspólne z IOException s oraz SQLException s.

W rzadkich przypadkach, w których chcesz przetestować pod kątem określonego komunikatu wyjątku, użyjesz nowego, ExpectedException JUnit @Rule.

@Rule 
public ExpectedException thrown= ExpectedException.none(); 
@Test 
public void messageIncludesErrantTemperature() { 
    thrown.expect(IllegalArgumentException.class); 
    thrown.expectMessage("-400"); // Tests that the message contains -400. 
    temperatureGauge.setTemperature(-400); 
} 

Teraz chyba setTemperature zgłasza IAE i wiadomość zawiera temperaturę użytkownik starał się ustawić, test nie powiedzie się. Z tej reguły można korzystać w bardziej wyrafinowany sposób.


Twój przykład można najlepiej obsługiwane przez:

private void testNumber(String word, int number) 
     throws OutOfRangeNumberException { 
    assertEquals(word, service.convert(number)); 
} 

@Test 
public final void testZero() 
     throws OutOfRangeNumberException { 
    testNumber("zero", 0); 
} 

Można inline testNumber; teraz to niewiele pomaga. Możesz to zmienić w sparametryzowaną klasę testową.

2

Istnieje kilka strategii, które są otwarte, aby poradzić sobie z oczekiwanymi wyjątkami w testach. Myślę, że adnotacje JUnit i idiota try/catch zostały już wspomniane powyżej. Chciałbym zwrócić uwagę na opcję Lambda w Java 8.

Na przykład biorąc pod uwagę:

class DummyService { 
public void someMethod() { 
    throw new RuntimeException("Runtime exception occurred"); 
} 

public void someOtherMethod(boolean b) { 
    throw new RuntimeException("Runtime exception occurred", 
      new IllegalStateException("Illegal state")); 
} 

}

Można to zrobić:

@Test 
public void verifiesCauseType() { 
    // lambda expression 
    assertThrown(() -> new DummyService().someOtherMethod(true)) 
      // assertions 
      .isInstanceOf(RuntimeException.class) 
      .hasMessage("Runtime exception occurred") 
      .hasCauseInstanceOf(IllegalStateException.class); 
} 

Spójrz na tego bloga, który obejmuje większość opcji z przykładów.

http://blog.codeleak.pl/2013/07/3-ways-of-handling-exceptions-in-junit.html

A ten wyjaśnia opcję Java 8 Lambda pełniej:

http://blog.codeleak.pl/2014/07/junit-testing-exception-with-java-8-and-lambda-expressions.html

Powiązane problemy