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.

12voto

Hugh Perkins Punkte 7016

Ich habe viele der hier vorgestellten Methoden ausprobiert, aber sie waren entweder kompliziert oder entsprachen nicht ganz meinen Anforderungen. In der Tat kann man eine Hilfsmethode ganz einfach schreiben:

public class ExceptionAssertions {
    public static void assertException(BlastContainer blastContainer ) {
        boolean caughtException = false;
        try {
            blastContainer.test();
        } catch( Exception e ) {
            caughtException = true;
        }
        if( !caughtException ) {
            throw new AssertionFailedError("exception expected to be thrown, but was not");
        }
    }
    public static interface BlastContainer {
        public void test() throws Exception;
    }
}

Verwenden Sie es so:

assertException(new BlastContainer() {
    @Override
    public void test() throws Exception {
        doSomethingThatShouldExceptHere();
    }
});

Keine Abhängigkeiten: keine Notwendigkeit für mockito, keine Notwendigkeit powermock; und funktioniert einfach gut mit endgültigen Klassen.

0 Stimmen

Interessant, passt aber nicht zu AAA (Arrange Act Assert), wo man den Act- und den Assert-Schritt in eigentlich unterschiedlichen Schritten durchführen möchte.

1 Stimmen

@bln-tom Technisch gesehen sind es zwei verschiedene Schritte, sie sind nur nicht in dieser Reihenfolge. ;p

12voto

Mark Bessey Punkte 19301

JUnit verfügt über eine eingebaute Unterstützung für diese Funktion, mit einer Attribut "erwartet" .

10voto

Mike Nakis Punkte 49916

Java 8 Lösung

Wenn Sie eine Lösung wünschen, die:

  • Verwendet Java 8-Lambdas
  • Hat nicht von irgendeiner JUnit-Magie abhängen
  • Ermöglicht die Prüfung auf mehrere Ausnahmen innerhalb einer einzigen Testmethode
  • Überprüft, ob eine Ausnahme von einer bestimmten Gruppe von Zeilen innerhalb Ihrer Testmethode ausgelöst wird, anstatt von jeder unbekannten Zeile in der gesamten Testmethode
  • Liefert das tatsächliche Ausnahmeobjekt, das ausgelöst wurde, so dass Sie es weiter untersuchen können

Hier ist eine Dienstprogrammfunktion, die ich geschrieben habe:

public final <T extends Throwable> T expectException( Class<T> exceptionClass, Runnable runnable )
{
    try
    {
        runnable.run();
    }
    catch( Throwable throwable )
    {
        if( throwable instanceof AssertionError && throwable.getCause() != null )
            throwable = throwable.getCause(); //allows testing for "assert x != null : new IllegalArgumentException();"
        assert exceptionClass.isInstance( throwable ) : throwable; //exception of the wrong kind was thrown.
        assert throwable.getClass() == exceptionClass : throwable; //exception thrown was a subclass, but not the exact class, expected.
        @SuppressWarnings( "unchecked" )
        T result = (T)throwable;
        return result;
    }
    assert false; //expected exception was not thrown.
    return null; //to keep the compiler happy.
}

( aus meinem Blog )

Verwenden Sie es wie folgt:

@Test
public void testMyFunction()
{
    RuntimeException e = expectException( RuntimeException.class, () -> 
        {
            myFunction();
        } );
    assert e.getMessage().equals( "I haz fail!" );
}

public void myFunction()
{
    throw new RuntimeException( "I haz fail!" );
}

9voto

Macchiatow Punkte 607

In meinem Fall erhalte ich immer RuntimeException von db, aber Nachrichten unterscheiden. Und die Ausnahme muss entsprechend behandelt werden. Hier ist, wie ich es getestet:

@Test
public void testThrowsExceptionWhenWrongSku() {

    // Given
    String articleSimpleSku = "999-999";
    int amountOfTransactions = 1;
    Exception exception = null;

    // When
    try {
        createNInboundTransactionsForSku(amountOfTransactions, articleSimpleSku);
    } catch (RuntimeException e) {
        exception = e;
    }

    // Then
    shouldValidateThrowsExceptionWithMessage(exception, MESSAGE_NON_EXISTENT_SKU);
}

private void shouldValidateThrowsExceptionWithMessage(final Exception e, final String message) {
    assertNotNull(e);
    assertTrue(e.getMessage().contains(message));
}

1 Stimmen

Vor der Zeile mit } catch ( sollten Sie einfügen fail("no exception thrown");

6voto

Jobin Punkte 5104

In JUnit 4 oder höher können Sie die Ausnahmen wie folgt testen

@Rule
public ExpectedException exceptions = ExpectedException.none();

bietet eine Vielzahl von Funktionen, die zur Verbesserung unserer JUnit-Tests verwendet werden können.
Im folgenden Beispiel teste ich 3 Dinge im Zusammenhang mit der Ausnahme.

  1. Der Typ der ausgelösten Ausnahme
  2. Die Ausnahme Nachricht
  3. Die Ursache der Ausnahme

    public class MyTest {

    @Rule
    public ExpectedException exceptions = ExpectedException.none();
    
    ClassUnderTest classUnderTest;
    
    @Before
    public void setUp() throws Exception {
        classUnderTest = new ClassUnderTest();
    }
    
    @Test
    public void testAppleisSweetAndRed() throws Exception {
    
        exceptions.expect(Exception.class);
        exceptions.expectMessage("this is the exception message");
        exceptions.expectCause(Matchers.<Throwable>equalTo(exceptionCause));
    
        classUnderTest.methodUnderTest("param1", "param2");
    }

    }

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