2296 Stimmen

Wie können Sie sicherstellen, dass eine bestimmte Ausnahme in JUnit 4-Tests ausgelöst wird?

Wie kann ich JUnit4 idiomatisch verwenden, um zu testen, dass ein Code eine Ausnahme auslöst?

Ich kann so etwas zwar durchaus machen:

@Test
public void testFooThrowsIndexOutOfBoundsException() {
  boolean thrown = false;

  try {
    foo.doStuff();
  } catch (IndexOutOfBoundsException e) {
    thrown = true;
  }

  assertTrue(thrown);
}

Ich erinnere mich, dass es eine Annotation oder eine Assert.xyz oder etwas die für diese Art von Situationen weit weniger plump und weit mehr im Geiste von JUnit ist.

27 Stimmen

Das Problem bei allen anderen Ansätzen ist, dass sie den Test immer beenden, sobald die Ausnahme ausgelöst wurde. Ich hingegen möchte oft noch org.mockito.Mockito.verify mit verschiedenen Parametern, um sicherzustellen, dass bestimmte Dinge geschehen (z. B. dass ein Logger-Dienst mit den richtigen Parametern aufgerufen wurde), bevor die Ausnahme ausgelöst wird.

5 Stimmen

Sie können sehen, wie man Ausnahmen Test in JUnit Wiki-Seite github.com/junit-team/junit/wiki/Exception-testing

6 Stimmen

@ZeroOne - Für das würde ich zwei verschiedene Tests haben - eine für die Ausnahme und eine, um die Interaktion mit Ihrem Mock zu überprüfen.

6voto

Shessuky Punkte 1558

Wir können eine Fail-Assertion nach der Methode verwenden, die eine Ausnahme zurückgeben muss:

try{
   methodThatThrowMyException();
   Assert.fail("MyException is not thrown !");
} catch (final Exception exception) {
   // Verify if the thrown exception is instance of MyException, otherwise throws an assert failure
   assertTrue(exception instanceof MyException, "An exception other than MyException is thrown !");
   // In case of verifying the error message
   MyException myException = (MyException) exception;
   assertEquals("EXPECTED ERROR MESSAGE", myException.getMessage());
}

3 Stimmen

Die zweite catch würde den Stack-Trace verschlucken, wenn eine andere Ausnahme ausgelöst wird, wodurch nützliche Informationen verloren gehen

6voto

Tor P Punkte 1341

Erstellen Sie einfach einen Matcher, der ein- und ausgeschaltet werden kann, etwa so:

public class ExceptionMatcher extends BaseMatcher<Throwable> {
    private boolean active = true;
    private Class<? extends Throwable> throwable;

    public ExceptionMatcher(Class<? extends Throwable> throwable) {
        this.throwable = throwable;
    }

    public void on() {
        this.active = true;
    }

    public void off() {
        this.active = false;
    }

    @Override
    public boolean matches(Object object) {
        return active && throwable.isAssignableFrom(object.getClass());
    }

    @Override
    public void describeTo(Description description) {
        description.appendText("not the covered exception type");
    }
}

Zur Verwendung:

hinzufügen. public ExpectedException exception = ExpectedException.none(); , dann:

ExceptionMatcher exMatch = new ExceptionMatcher(MyException.class);
exception.expect(exMatch);
someObject.somethingThatThrowsMyException();
exMatch.off();

5voto

Srini Punkte 1580

Zusätzlich zu dem, was NamShubWriter hat gesagt, stellen Sie sicher, dass:

  • Die ExpectedException-Instanz ist öffentlich ( Verwandte Frage )
  • Die ExpectedException ist nicht die beispielsweise in der @Before-Methode instanziiert werden. Diese Beitrag erklärt anschaulich alle Feinheiten der Ausführungsreihenfolge von JUnit.

Haga nicht dies tun:

@Rule    
public ExpectedException expectedException;

@Before
public void setup()
{
    expectedException = ExpectedException.none();
}

Endlich, diese Blog-Beitrag zeigt deutlich, wie man behauptet, dass eine bestimmte Ausnahme ausgelöst wurde.

4voto

Donatello Punkte 3066

Die Junit4-Lösung mit Java8 besteht darin, diese Funktion zu verwenden:

public Throwable assertThrows(Class<? extends Throwable> expectedException, java.util.concurrent.Callable<?> funky) {
    try {
        funky.call();
    } catch (Throwable e) {
        if (expectedException.isInstance(e)) {
            return e;
        }
        throw new AssertionError(
                String.format("Expected [%s] to be thrown, but was [%s]", expectedException, e));
    }
    throw new AssertionError(
            String.format("Expected [%s] to be thrown, but nothing was thrown.", expectedException));
}

Die Verwendung ist dann:

    assertThrows(ValidationException.class,
            () -> finalObject.checkSomething(null));

Beachten Sie, dass die einzige Einschränkung die Verwendung einer final Objektreferenz im Lambda-Ausdruck. Diese Lösung ermöglicht es, die Testaussagen fortzusetzen, anstatt auf Methodenebene mit @Test(expected = IndexOutOfBoundsException.class) Lösung.

4voto

Piotr Rogowski Punkte 3294

Ich empfehle die Bibliothek assertj-core Behandlung von Ausnahmen im Junit-Test

In Java 8, etwa so:

//given

//when
Throwable throwable = catchThrowable(() -> anyService.anyMethod(object));

//then
AnyException anyException = (AnyException) throwable;
assertThat(anyException.getMessage()).isEqualTo("........");
assertThat(exception.getCode()).isEqualTo(".......);

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X