JUnit test — analysing expected Exceptions
在JUnit中,我目前正在使用注释来期待我的测试中的异常。
有没有办法分析这个例外? 例如,我期望
如果您有JUnit 4.7或更高版本,请尝试ExpectedException
这个问题有一个例子,复制如下:
1 2 3 4 5 6 7 8 9 | @Rule public ExpectedException exception = ExpectedException.none(); @Test public void testRodneCisloRok(){ exception.expect(IllegalArgumentException.class); exception.expectMessage("error1"); new RodneCislo("891415",dopocitej("891415")); } |
我不确定你是否应该这样做。使用try-catch块来检查错误消息是如此junit3ish。我们现在有这个很酷的功能,您可以编写
IMO你应该留下
通常,您希望测试方法是否抛出异常,而不是实际的错误消息。如果错误消息非常重要,您应该考虑使用它抛出的异常的子类并在
1 2 3 4 5 6 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()); } |
如果要测试许多测试用例,请使用MethodRule作为常用解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public class ExceptionRule implements MethodRule { @Override public Statement apply(final Statement base, final FrameworkMethod method, Object target) { return new Statement() { @Override public void evaluate() throws Throwable { try { base.evaluate(); Assert.fail(); } catch (CriticalServerException e) { //Analyze the exception here } } }; } } |
然后将规则用于您的测试类:
1 | @Rule public ExceptionRule rule = new ExceptionRule(); |
1 2 3 4 5 6 | try { // test code invacation fail("Exception not throw!!!"); } catch(CriticalServerException ex) { assertTrue("Invalid exception data", ex.toString().contains("error text")); } |
1 2 3 4 5 6 7 8 9 10 | try { // your code fail("Didn't throw expected exception"); } catch(CriticalServerException e) { assertEquals("Expected message", e.getMessage()); } |
我不认为有一种方法可以使用注释。您可能必须回退到try-catch方式,在catch块中您可以验证消息
Java 8解决方案
这是我写的一个实用函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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. } |
(摘自我的博客)
使用方法如下:
1 2 3 4 5 6 7 8 9 | @Test public void testThrows() { RuntimeException e = expectException( RuntimeException.class, () -> { throw new RuntimeException("fail!" ); } ); assert e.getMessage().equals("fail!" ); } |
此外,如果您想阅读一些您不希望查看异常消息的原因,请参阅:https://softwareengineering.stackexchange.com/a/278958/41811
如果您想将消息与异常类型进行比较,那么您可以尝试下面的代码片段。
1 2 3 4 5 6 | @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 |
注意:这适用于junit 4.9以后。
看看流畅的异常规则,它"结合了Junit ExpectedException规则和AssertJ的断言方便性。"
1 2 3 4 5 6 7 8 9 10 | 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(); } |
使用catch-exception:
1 2 3 | catchException(obj).doSomethingCritical(); assertTrue(caughtException() instanceof CriticalServerException); assertEquals("Expected Message", caughtException().getMessage()); |