如何用JUnit Test注解来断言我的exception消息?

我用@Test注解编写了一些JUnittesting。 如果我的testing方法抛出一个检查exception,如果我想断言与exception的消息,是否有办法用JUnit @Test注释这样做? AFAIK,JUnit 4.7不提供这个function,但是未来的版本是否提供这个function呢? 我知道在.NET中,你可以断言消息和exception类。 在Java世界中寻找类似的function。

这就是我要的:

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

您可以使用ExpectedException@Rule注释,如下所示:

 @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... } 

请注意, ExpectedException文档中的示例(当前)是错误的 – 没有公共构造函数,因此您必须使用ExpectedException.none()

你必须使用@Test(expected=SomeException.class) ? 当我们必须断言例外的实际信息时,这就是我们所做的。

 @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()); } } 

我喜欢@Rule答案。 但是,如果由于某种原因您不想使用规则。 还有第三种select。

 @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!"); } 

雷暴风暴有一个很好的答案。 我也不是规则的忠实粉丝。 我做了类似的事情,除了我创build了下面的工具类,以帮助可读性和可用性,这是注释的最大优点之一。

添加这个工具类:

 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(); } 

那么对于我的unit testing,我只需要这个代码:

 @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" } 

其实最好的用法就是try / catch。 为什么? 因为你可以控制你所期望的例外。

考虑这个例子:

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

如果有一天代码被修改,testing准备会抛出一个RuntimeException? 在这种情况下,实际testing甚至没有经过testing,即使没有抛出任何exception,testing也会通过。

这就是为什么使用try / catch要比依赖注释更好。

如果使用@Rule,则将exception集应用于Test类中的所有testing方法。

导入捕获exception库,并使用它。 它比ExpectedException规则或try-catch更清洁。

示例形成他们的文档:

 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() ) );