java - handling - JUnit-Test-erwartete Exceptions analysieren



junit exception handling (8)

Java 8 Lösung

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 "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 )

Benutze es wie folgt:

@Test
public void testThrows()
{
    RuntimeException e = expectException( RuntimeException.class, () -> 
        {
            throw new RuntimeException( "fail!" );
        } );
    assert e.getMessage().equals( "fail!" );
}

Wenn Sie außerdem einige Gründe lesen möchten, warum Sie die Nachricht Ihrer Ausnahme nicht überprüfen sollten , finden Sie unter https://softwareengineering.stackexchange.com/a/278958/41811

https://src-bin.com

Diese Frage hat hier bereits eine Antwort:

In JUnit verwende ich Annotation, um eine Ausnahme in meinen Tests zu erwarten.

Gibt es eine Möglichkeit, diese Ausnahme zu analysieren? Zum Beispiel erwarte ich eine CriticalServerException , aber ich möchte auch den Inhalt der getMessage Methode überprüfen.


Answer #1

Ich bin mir nicht sicher, ob du das solltest. Verwenden Sie einen try-catch-Block, um die Fehlermeldung zu prüfen, so ist junit3ish . Wir haben jetzt dieses coole Feature, dass Sie @Test(expected=CriticalServerException.class) schreiben @Test(expected=CriticalServerException.class) und Sie wollen "zurück" gehen und try-catch erneut verwenden, um eine Ausnahme zu erhalten, die Sie erwarten, nur um die Fehlermeldung zu überprüfen?

IMO sollten Sie für die Annotation @Test(expected=CriticalServerException.class) bleiben und die Fehlermeldung ignorieren. Das Überprüfen der Fehlermeldung, die viel geändert werden kann, da sie eine "menschlichere" Zeichenfolge und kein technischer Wert ist, kann ebenfalls schwierig sein. Sie erzwingen die Ausnahme mit einer spezifischen Fehlermeldung, aber Sie wissen möglicherweise nicht, wer die Ausnahme generiert hat und welche Fehlermeldung er gewählt hat.

Im Allgemeinen möchten Sie testen, ob die Methode die Ausnahme auslöst oder nicht und nicht wie die tatsächliche Fehlermeldung aussieht. Wenn die Fehlermeldung wirklich so wichtig ist, sollten Sie vielleicht eine Unterklasse der Exception, die sie @Test(expected=...) in @Test(expected=...) und sie in @Test(expected=...) überprüfen @Test(expected=...) .


Answer #2

Sehen Sie sich die fluent fluent-exception-rule , sie "kombiniert die Junit ExpectedException-Regel und die AssertJ-Assertions-Convenience".

import pl.wkr.fluentrule.api.FluentExpectedException;
...
@Rule
public FluentExpectedException thrown = FluentExpectedException.none();

@Test
public void testDoSomethingCritical() {
    thrown.expect(CriticalServerException.class).hasMessage("Expected Message").hasNoCause();
    obj.doSomethingCritical();
}

Answer #3

Verwenden Sie catch-exception :

catchException(obj).doSomethingCritical();
assertTrue(caughtException() instanceof CriticalServerException);
assertEquals("Expected Message", caughtException().getMessage());

Answer #4

Wenn Sie JUnit 4.7 oder höher haben, versuchen Sie ExpectedException

Es gibt ein Beispiel in dieser Frage , die unten kopiert wird:

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

@Test
public void testRodneCisloRok(){
    exception.expect(IllegalArgumentException.class);
    exception.expectMessage("error1");
    new RodneCislo("891415",dopocitej("891415"));
}

Answer #5

Wenn Sie die Nachricht zusammen mit dem Ausnahmetyp vergleichen möchten, können Sie das folgende Code-Snippet ausprobieren.

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

    expectedException.expect(IllegalArgumentException.class);
    expectedException.expectMessage("Parameter is not valid"); //check string contains
    expectedException.expectMessage(CoreMatchers.equalTo("Parameter is not valid")); //check string equals

Hinweis: Dies funktioniert ab Juni 4.9.


Answer #6
try {
    // test code invacation
    fail("Exception not throw!!!");
} catch(CriticalServerException ex) {
    assertTrue("Invalid exception data", ex.toString().contains("error text"));
}

Answer #7
try{ 
    //your code expecting to throw an exception
    fail("Failed to assert :No exception thrown");
} catch(CriticalServerException ex){
    assertNotNull("Failed to assert", ex.getMessage()) 
    assertEquals("Failed to assert", "Expected Message", ex.getMessage());
}




junit