点击跳转到系列博文目录导航
Junit5中新添加了对方法抛出异常的断言Assertions类中的assertThrows()和assertDoesNotThrow(),使用此方法可以对被测试方法抛出的异常进行断言测试,而在junit4中的对异常进行断言实现相对来说比较麻烦的。
下面来看一些案例使用:
其中每个方法的作用代码中的注释写的已经非常清楚了
,就不再赘述了.
大家最好将代码自己测试一遍,可以加深理解与记忆!
案例代码:
1.使用到的被测试方法
public class AssertTestModel {
public static void testThrowArithmeticException(int numA,int numB){
try {
int result = numA/numB;
}catch (ArithmeticException e){
throw new ArithmeticException("The numB not allowed to '0'!!");
}
}
}
2.测试案例
import cn.yoylee.junit5.AssertTestModel;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author liyangyang
* @date 2019/1/14
*/
class AssertThrowsTest {
@Test
void testAssertThrows(){
//2:如果抛出的异常与设定的异常相同,则这一步的断言成功并返回一个异常的顶级父类
Throwable exception = assertThrows(ArithmeticException.class,()->{
//1:执行此语句会抛出一个ArithmeticException异常,被assertThrows方法捕获
AssertTestModel.testThrowArithmeticException(2,0);
});
//3:接下来便可以对返回的异常进行一些其他的测试
//比如对异常的信息进行断言测试等。。
assertEquals("The numB not allowed to '0'!!",exception.getMessage());
}
@Test
void testAssertDoesNotThrow1(){
//因为函数式编程中的执行语句抛出了异常,所以断言失败
assertDoesNotThrow(()->{
AssertTestModel.testThrowArithmeticException(2,0);
});
}
@Test
void testAssertDoesNotThrow2(){
//断言成功
assertDoesNotThrow(()->{
AssertTestModel.testThrowArithmeticException(2,1);
});
}
@Test
void testtestAssertDoesSNotThrowHaveReturn(){
//这是带返回参数的assertDoesNotThrow方法,在没有异常抛出的情况下会返回一个值
int re = assertDoesNotThrow(() -> {
int result = AssertTestModel.testThrowArithmeticException(2,1);
return result;
});
//其实上面的语句可以简化为下面的语句不过为了便于理解,还是使用的上述表达
// int re = assertDoesNotThrow(() -> AssertTestModel.testThrowArithmeticException(2,1));
//可以对返回的结果值进行一些测试等
assertEquals(re,2);
}
}
到这里大家应该已经知道如何使用这两个方法了,但是其执行过程是怎样的,怎样设计的呢?我们接下来看一下
首先,assertThrows有三个重载方法:
public static <T extends Throwable> T assertThrows(Class<T> expectedType, Executable executable) {
return AssertThrows.assertThrows(expectedType, executable);
}
public static <T extends Throwable> T assertThrows(Class<T> expectedType, Executable executable, String message) {
return AssertThrows.assertThrows(expectedType, executable, message);
}
public static <T extends Throwable> T assertThrows(Class<T> expectedType, Executable executable, Supplier<String> messageSupplier) {
return AssertThrows.assertThrows(expectedType, executable, messageSupplier);
}
我们可以看到,其中都是调用了AssertThrows.assertThrows
方法,这里的AssertThrows和Assertions的关系和我们在Junit5系列-Junit5中Assertions断言类一文中Assertions和assertTrue关系一样。
接下来就看一下AssertThrows.assertThrows()
到底是何许人也:
private static <T extends Throwable> T assertThrows(Class<T> expectedType, Executable executable, Object messageOrSupplier) {
try {
//执行参数executable中设置的语句
executable.execute();
} catch (Throwable var5) {
//判断捕获的异常是否和自定义的异常类相同,相同则返回异常对象
if (expectedType.isInstance(var5)) {
return var5;
}
//如果捕获的异常和自定义的异常不同,通过自定义的打印信息messageOrSupplier组装异常并抛出(AssertionFailedError为Junit5的自定义异常)
String message = AssertionUtils.buildPrefix(AssertionUtils.nullSafeGet(messageOrSupplier)) + AssertionUtils.format(expectedType, var5.getClass(), "Unexpected exception type thrown");
throw new AssertionFailedError(message, var5);
}
//如果执行的语句没有异常,组装“没有异常的”异常抛出
String message = AssertionUtils.buildPrefix(AssertionUtils.nullSafeGet(messageOrSupplier)) + String.format("Expected %s to be thrown, but nothing was thrown.", AssertionUtils.getCanonicalName(expectedType));
throw new AssertionFailedError(message);
}
我在源码中注释了其运行过程,相对来说是比较简单的,这里的参数参数介绍一下:
,继承自Throwable类的子类型,必须是继承Throwable的子类。所以我们在测试方法中可以直接使用Throwable接受返回值。Class expectedType
,定义想要测试的异常类型Object messageOrSupplier
,这里Object类型的原因是可能会接受String类型的自定义信息类型,还有可能接受函数式接口Supplier的自定义信息。Executable executable
,函数式接口,可以使用lambda表达式,可以稍微看一下其源码:@FunctionalInterface
@API(
status = Status.STABLE,
since = "5.0"
)
public interface Executable {
void execute() throws Throwable;
}
其中@FunctionalInterface
可以看出是一个函数式接口,无参无返回值的调用方法。
好了,到这里大家应该对assertThrows方法有个全面的了解,对于的assertDoseNotThrows方法来说,实现方式类似,有6个重载方法,3个有返回值的3个无返回值的重载, 最后都是调用的AssertDoesNotThrow.assertDoesNotThrow()方法实现的,其源码为:
//泛型返回值
private static <T> T assertDoesNotThrow(ThrowingSupplier<T> supplier, Object messageOrSupplier) {
try {
//函数式接口方法执行,无异常正常返回
return supplier.get();
} catch (Throwable var4) {
//捕获异常则根据messageOrSupplier自定义消息组装异常并抛出
String message = AssertionUtils.buildPrefix(AssertionUtils.nullSafeGet(messageOrSupplier)) + "Unexpected exception thrown: " + var4.getClass().getName();
throw new AssertionFailedError(message, var4);
}
}
如果转载此博文,请附上本文链接,谢谢合作~ :https://blog.csdn.net/csdn___lyy
如果感觉这篇文章对您有所帮助,请点击一下“喜欢”或者“关注”博主,您的喜欢和关注将是我前进的最大动力!