如何使用JUnit来测试某些代码是否抛出异常?
我当然可以这样做:
@Test
public void testFooThrowsIndexOutOfBoundsException() {
boolean thrown = false;
try {
foo.doStuff();
} catch (IndexOutOfBoundsException e) {
thrown = true;
}
assertTrue(thrown);
}
我记得,对于这类情况,有一个注释或Assert.xyz之类的东西远没有JUnit那么笨拙,更符合JUnit的精神。
我在这里尝试了许多方法,但它们要么很复杂,要么不太符合我的要求。事实上,可以非常简单地编写一个助手方法:
public class ExceptionAssertions {
public static void assertException(BlastContainer blastContainer ) {
boolean caughtException = false;
try {
blastContainer.test();
} catch( Exception e ) {
caughtException = true;
}
if( !caughtException ) {
throw new AssertionFailedError("exception expected to be thrown, but was not");
}
}
public static interface BlastContainer {
public void test() throws Exception;
}
}
这样使用:
assertException(new BlastContainer() {
@Override
public void test() throws Exception {
doSomethingThatShouldExceptHere();
}
});
零依赖:无需mockito,无需powermock;在期末考试中表现很好。
Java 8解决方案
如果您想要一个解决方案:
利用Java 8 lambda不依赖任何JUnit魔法允许您检查单个测试方法中的多个异常检查测试方法中特定的一组行(而不是整个测试方法中的任何未知行)是否引发异常生成引发的实际异常对象,以便您可以进一步检查它
下面是我编写的实用函数:
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 testing for "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.
}
(摘自我的博客)
使用方法如下:
@Test
public void testMyFunction()
{
RuntimeException e = expectException( RuntimeException.class, () ->
{
myFunction();
} );
assert e.getMessage().equals( "I haz fail!" );
}
public void myFunction()
{
throw new RuntimeException( "I haz fail!" );
}