如何用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() ) );