Frage

Ich habe ein paar JUnit-Tests mit @Test Anmerkung geschrieben. Wenn mein Testmethode geprüft Würfe eine Ausnahme, und wenn ich die Nachricht zusammen mit der Ausnahme behaupten will, ist es eine Möglichkeit, so mit JUnit @Test Anmerkung zu tun? AFAIK, JUnit 4.7 diese Funktion nicht zur Verfügung stellen, aber nicht alle zukünftigen Versionen es schaffen? Ich weiß, in .NET können Sie die Nachricht behaupten und die Ausnahmeklasse. Suchen Sie nach ähnlicher Funktion in der Java-Welt.

Das ist, was ich will:

@Test (expected = RuntimeException.class, message = "Employee ID is null")
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() {}
War es hilfreich?

Lösung

Sie können verwenden die @Rule Anmerkung mit ExpectedException , wie folgt aus:

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

@Test
public void shouldThrowRuntimeExceptionWhenEmployeeIDisNull() throws Exception {
    expectedEx.expect(RuntimeException.class);
    expectedEx.expectMessage("Employee ID is null");

    // do something that should throw the exception...
    System.out.println("=======Starting Exception process=======");
    throw new NullPointerException("Employee ID is null");
}

Beachten Sie, dass das Beispiel in den ExpectedException docs ist (derzeit) falsch -. Es gibt keinen öffentlichen Konstruktor, so dass Sie verwenden ExpectedException.none() haben

Andere Tipps

Ich mag die @Rule Antwort. Wenn jedoch aus irgendeinem Grund Sie nicht wollen, Regeln verwenden. Es gibt eine dritte Option.

@Test (expected = RuntimeException.class)
public void myTestMethod()
{
   try
   {
      //Run exception throwing operation here
   }
   catch(RuntimeException re)
   {
      String message = "Employee ID is null";
      assertEquals(message, re.getMessage());
      throw re;
    }
    fail("Employee Id Null exception did not throw!");
  }

Haben Sie @Test(expected=SomeException.class) zu benutzen? Wenn wir die eigentliche Nachricht der Ausnahme geltend zu machen haben, das ist, was wir tun.

@Test
public void myTestMethod()
{
  try
  {
    final Integer employeeId = null;
    new Employee(employeeId);
    fail("Should have thrown SomeException but did not!");
  }
  catch( final SomeException e )
  {
    final String msg = "Employee ID is null";
    assertEquals(msg, e.getMessage());
  }
}

In JUnit 4,13 (einmal freigegeben) Sie tun können:

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;

...

@Test
void exceptionTesting() {
  IllegalArgumentException exception = assertThrows(
    IllegalArgumentException.class, 
    () -> { throw new IllegalArgumentException("a message"); }
  );

  assertEquals("a message", exception.getMessage());
}

Dies funktioniert auch in JUnit 5 aber mit unterschiedlichen Importe:

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

...

Eigentlich ist die beste Nutzung ist mit try / catch. Warum? Denn man kann den Ort kontrollieren, wo Sie die Ausnahme erwarten.

Betrachten Sie dieses Beispiel:

@Test (expected = RuntimeException.class)
public void someTest() {
   // test preparation
   // actual test
}

Was ist der Code, wenn eines Tages geändert und Testvorbereitung wird eine Runtime werfen? In diesem Fall wird die tatsächliche Prüfung nicht einmal getestet und auch wenn es keine Ausnahme wirft wird der Test.

Aus diesem Grunde ist es viel besser zu Einsatz try / catch als auf der Anmerkung zu verlassen.

Raystorm hatte eine gute Antwort. Ich bin kein großer Fan von Regeln auch nicht. Ich tue etwas ähnlich, außer dass ich die folgende Utility-Klasse, um Hilfe Lesbarkeit zu erstellen und Benutzerfreundlichkeit, die eine der großen plus'es von Anmerkungen an erster Stelle ist.

Fügen Sie diese Utility-Klasse:

import org.junit.Assert;

public abstract class ExpectedRuntimeExceptionAsserter {

    private String expectedExceptionMessage;

    public ExpectedRuntimeExceptionAsserter(String expectedExceptionMessage) {
        this.expectedExceptionMessage = expectedExceptionMessage;
    }

    public final void run(){
        try{
            expectException();
            Assert.fail(String.format("Expected a RuntimeException '%s'", expectedExceptionMessage));
        } catch (RuntimeException e){
            Assert.assertEquals("RuntimeException caught, but unexpected message", expectedExceptionMessage, e.getMessage());
        }
    }

    protected abstract void expectException();

}

Dann für mein Gerät zu testen, alles was ich brauche ist dieser Code:

@Test
public void verifyAnonymousUserCantAccessPrivilegedResourceTest(){
    new ExpectedRuntimeExceptionAsserter("anonymous user can't access privileged resource"){
        @Override
        protected void expectException() {
            throw new RuntimeException("anonymous user can't access privileged resource");
        }
    }.run(); //passes test; expected exception is caught, and this @Test returns normally as "Passed"
}

Wenn @Rule verwendet, wird die Ausnahme-Set für alle Testmethoden in der Test-Klasse angewandt.

Ich mag die Antwort von user64141 aber festgestellt, dass es verallgemeinert werden mehr könnte. Hier ist mein nehmen:

public abstract class ExpectedThrowableAsserter implements Runnable {

    private final Class<? extends Throwable> throwableClass;
    private final String expectedExceptionMessage;

    protected ExpectedThrowableAsserter(Class<? extends Throwable> throwableClass, String expectedExceptionMessage) {
        this.throwableClass = throwableClass;
        this.expectedExceptionMessage = expectedExceptionMessage;
    }

    public final void run() {
        try {
            expectException();
        } catch (Throwable e) {
            assertTrue(String.format("Caught unexpected %s", e.getClass().getSimpleName()), throwableClass.isInstance(e));
            assertEquals(String.format("%s caught, but unexpected message", throwableClass.getSimpleName()), expectedExceptionMessage, e.getMessage());
            return;
        }
        fail(String.format("Expected %s, but no exception was thrown.", throwableClass.getSimpleName()));
    }

    protected abstract void expectException();

}

Beachten Sie, dass Verlassen der „nicht bestanden“ Anweisung im try-Block bewirkt, dass die damit verbundene Behauptung Ausnahme gefangen werden; durch Rücksendung innerhalb der catch-Anweisung verhindert dies.

Importieren Sie die catch-Ausnahme Bibliothek und verwendet diesen. Es ist viel sauberer als die ExpectedException Regel oder ein try-catch.

Beispiel bilden ihre docs:

import static com.googlecode.catchexception.CatchException.*;
import static com.googlecode.catchexception.apis.CatchExceptionHamcrestMatchers.*;

// given: an empty list
List myList = new ArrayList();

// when: we try to get the first element of the list
catchException(myList).get(1);

// then: we expect an IndexOutOfBoundsException with message "Index: 1, Size: 0"
assertThat(caughtException(),
  allOf(
    instanceOf(IndexOutOfBoundsException.class),
    hasMessage("Index: 1, Size: 0"),
    hasNoCause()
  )
);
@Test (expectedExceptions = ValidationException.class, expectedExceptionsMessageRegExp = "This is not allowed")
public void testInvalidValidation() throws Exception{
     //test code
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top