前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Junit5系列-Junit5中assertThrows()与assertDoesNotThrow()方法详解

Junit5系列-Junit5中assertThrows()与assertDoesNotThrow()方法详解

作者头像
洋仔聊编程
发布2019-01-24 10:56:27
11.2K0
发布2019-01-24 10:56:27
举报

简介

Junit5中新添加了对方法抛出异常的断言Assertions类中的assertThrows()和assertDoesNotThrow(),使用此方法可以对被测试方法抛出的异常进行断言测试,而在junit4中的对异常进行断言实现相对来说比较麻烦的。

  • assertThrows()主要对被测试方法的抛出异常进行测试,测试所抛出的异常是否满足预期。
  • assertDoesNotThrow()主要用来判定被测试方法是否抛出了异常,如果抛出异常则断言失败,无异常抛出则断言成功。

下面来看一些案例使用:

案例分析

其中每个方法的作用代码中的注释写的已经非常清楚了,就不再赘述了.

大家最好将代码自己测试一遍,可以加深理解与记忆!

案例代码:

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

我在源码中注释了其运行过程,相对来说是比较简单的,这里的参数参数介绍一下:

  • 返回类型:<T extends Throwable>,继承自Throwable类的子类型,必须是继承Throwable的子类。所以我们在测试方法中可以直接使用Throwable接受返回值。
  • 参数:Class<T> 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 如果感觉这篇文章对您有所帮助,请点击一下“喜欢”或者“关注”博主,您的喜欢和关注将是我前进的最大动力!

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年01月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 案例分析
  • 源码分析
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档