前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Junit5系列-Junit5中Assertions断言类

Junit5系列-Junit5中Assertions断言类

作者头像
洋仔聊编程
发布2019-01-15 17:12:25
3.4K0
发布2019-01-15 17:12:25
举报

目录
  • 简介
  • 案例解析
  • 源码解析
  • Assertions与AssertNull

简介

junit5中的JUnit Jupiter提供了Assertions类来替代了junit4中的Assert类并且添加了一些新的方法,所以工作过程中完全可以使用Assertions代替Assert类。 其包名称为:org.junit.jupiter.api.Assertions Assertions中提供的方法都是静态方法,我们可以通过import静态资源进行使用,例如:

代码语言:javascript
复制
import static org.junit.jupiter.api.Assertions.*;

当然上述是导入了所有的方法,单独导入也可。

案例解析

下面对Assertions进行一个简单的应用 代码的注释都很清楚,就不再多说了

代码语言:javascript
复制
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;

import static java.time.Duration.ofMillis;
import static java.time.Duration.ofMinutes;
import static org.junit.jupiter.api.Assertions.*;
/**
 * @author liyangyang
 * @date 2019/1/8
 */
class AssertionsDemo {
    //定义一个person对象,Person类里面有两个参数lastName,firstName
    static Person person = new Person();

    /**
     * 使用 @BeforeAll注解在所有测试方法执行前执行person对象的赋值
     */
    @BeforeAll
    static void initPerson(){
        person.setFirstName("John");
        person.setLastName("Doe");
    }

    /**
     * assertEquals比较两个值是否相同
     * assertTrue 判断括号里面的参数是否为true
     */
    @Test
    void standardAssertions() {
        assertEquals(2, 2);
        //当不相等时,会打印出第三个参数,下面的所有的此类型的参数都是这种作用
        assertEquals(4, 5, "The optional assertion message is now the last parameter.");
        assertTrue('a' < 'b', "Assertion messages can be lazily evaluated -- "
                + "to avoid constructing complex messages unnecessarily.");
    }

    /**
     * assertAll()方法用于将多个测试语句放在一个组中执行
     * 组中若有一个测试语句不通过,则这个组将会一起报错.
     * 方法中第一个参数:组名称
     * 方法中第二个参数:组测试语句
     */
    @Test
    void groupedAssertions() {
        assertAll("person",
                () -> assertEquals("John", person.getFirstName()),
                () -> assertEquals("Doe", person.getLastName())
        );
    }

    /**
     * assertAll()方法也可以嵌套多个assertAll()方法
     * 其中嵌套的多个测试组,这些组只会打印出这个组和父组的错误,对其他的组没有影响
     */
    @Test
    void dependentAssertions() {
        assertAll("properties",
                //第一个测试组
                () -> {
                    String firstName = person.getFirstName();
                    assertNotNull(firstName);

                    assertAll("first name",
                            () -> assertTrue(firstName.startsWith("J")),
                            () -> assertTrue(firstName.endsWith("n"))
                    );
                },
                //第二个测试组
                () -> {
                    String lastName = person.getLastName();
                    assertNotNull(lastName);

                    assertAll("last name",
                            () -> assertTrue(lastName.startsWith("D")),
                            () -> assertTrue(lastName.endsWith("e"))
                    );
                }
        );
    }

    /**
     * assertThrows()可以用来判断lambda表达式中的代码抛出的异常
     * 比如下面案例就是测试了抛出异常的信息是否相同
     * 参数:
     * 1:异常类声明
     * 2:测试代码Lambda表达式
     */
    @Test
    void exceptionTesting() {
        Throwable exception = assertThrows(IllegalArgumentException.class, () -> {
            try {
                //这里只是简单的做个测试,当然1/0不该抛IllegalArgumentException异常 ,只是简单的测试一下
              int s = 1/0;
            }catch (Exception e){
                throw new IllegalArgumentException("a message");
            }
        });
        assertEquals("a message", exception.getMessage());
    }

    /**
     * assertTimeout()对方法执行时间进行测试
     * 这里要借助java.time.Duration中的方法结合实现
     * 实例中执行的代码部分必须在2分钟之内执行完毕,否则测试不通过
     */
    @Test
    void timeoutNotExceeded() {
        assertTimeout(ofMinutes(2), () -> {
            //执行的代码部分
        });
    }

    /**
     * assertTimeout()还可以接受一个返回值(泛型 T)
     * 被测试代码如果通过测试并返回一个值,这个值被assertTimeout()方法返回
     */
    @Test
    void timeoutNotExceededWithResult() {
        String actualResult = assertTimeout(ofMinutes(2), () -> {
            return "a result";
        });
        assertEquals("a result", actualResult);
    }

    /**
     * assertTimeout()毫秒案例
     */
    @Test
    void timeoutExceeded() {
        assertTimeout(ofMillis(10), () -> {
            Thread.sleep(100);
        });
    }
}

这里只是介绍一下其用法,其中还有好多方法没涉及到,者要等我们在使用的过程中再去查找合适的方法。

相信通过上述案例你应该对Assertions有个大体的了解, 下面再细说一下。

源码解析

因为代码太长了,就不贴代码了,大家有需要可以自行查看。 里面有好多静态测试方法,每个方法又有各自的重载。

在这里插入图片描述
在这里插入图片描述

这只是截取了不到三分之一的方法。

下面通过介绍public static void assertNull(Object actual, String message)这个判断对象为空的方法,来大致的看一下其实现过程。

  1. Assertions中的assertNull方法源码
代码语言:javascript
复制
 public static void assertNull(Object actual, String message) {
        AssertNull.assertNull(actual, message);
}

调用了AssertNull类中的assertNull方法

  1. AssertNull类中的assertNull方法源码
代码语言:javascript
复制
static void assertNull(Object actual, String message) {
        if (actual != null) {
            failNotNull(actual, message);
        }

}
  • 判断参数actual是否为null,若为null则表示测试成功,方法结束,不报错。
  • 如果参数actual不为空,则要调用failNotNull方法
  1. failNotNull方法源码
代码语言:javascript
复制
private static void failNotNull(Object actual, String message) {
        AssertionUtils.fail(AssertionUtils.buildPrefix(message) + "expected: <null> but was: <" + actual + ">", (Object)null, actual);
}

这个方法主要就是组装了错误消息,并将被验证参数传递到下一层

  1. fail方法源码
代码语言:javascript
复制
static void fail(String message, Object expected, Object actual) {
        throw new AssertionFailedError(message, expected, actual);
}

在这里直接抛出了一个自定义异常。 到这里一个测试的过程就几乎结束了,大体来说不难,大家如果还想了解其他的方法源码,可以自己debug跟踪源码来查看。

  1. 最后简单的看一下这个自定义异常AssertionFailedError吧 其继承关系为:
代码语言:javascript
复制
public class AssertionFailedError extends AssertionError
--->
public class AssertionError extends Error
--->
public class Error extends Throwable

可以看书这是正常的自定义异常的模式,继承JDK自带的java.long.error类,实现自己的Error类,这里的AssertionError是所有Assertions类中方法报错的父类,其他特定的错误类就是继承的此类。

Assertions与AssertNull

另外,在上述过程中我们知道,Assertions.assertNull()其实就是调用的AssertNull中的assertNull()实现的,我们看一下AssertNull的源码:

代码语言:javascript
复制
class AssertNull {
    private AssertNull() {
    }
    //包可见静态方法
    static void assertNull(Object actual) {
        assertNull(actual, (String)null);
    }
    //包可见静态方法
    static void assertNull(Object actual, String message) {
        if (actual != null) {
            failNotNull(actual, message);
        }

    }
    //包可见静态方法
    static void assertNull(Object actual, Supplier<String> messageSupplier) {
        if (actual != null) {
            failNotNull(actual, AssertionUtils.nullSafeGet(messageSupplier));
        }

    }
    //类内调用方法
    private static void failNotNull(Object actual, String message) {
        AssertionUtils.fail(AssertionUtils.buildPrefix(message) + "expected: <null> but was: <" + actual + ">", (Object)null, actual);
    }
}

再看一下这两个类是不是在一个包中:

在这里插入图片描述
在这里插入图片描述

从源码和图片中不难发现,AssertNull中其实和Assertions一样也是提供了包内可见的静态方法 ,所以我们也可以通过引入import static org.junit.jupiter.api.AssertNull.*;来直接使用AssertNull中的方法,不过这可不是个好想法。

Assertions将测试方法集中在该方法内,不仅便于管理,还减少代码的复杂度,性能没有任何影响,为什么要去直接使用AssertNull等类呢,嘿嘿

最后:当然,Assertions提供的断言方法虽然多,但有时候还是不够的,当Junit5不支持你的单元测试需求时,Junit5官方还是鼓励程序员去使用第三方支持库的,比如:AssertJ、Hamcrest,Truth等。。。。

如果转载此博文,请附上本文链接:https://blog.csdn.net/csdn___lyy ,谢谢合作~

如果感觉这篇文章对您有所帮助,请点击一下“喜欢”或者“关注”博主,您的喜欢和关注将是我前进的最大动力!

refer: 官网

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 简介
  • 案例解析
  • 源码解析
  • Assertions与AssertNull
相关产品与服务
容器镜像服务
容器镜像服务(Tencent Container Registry,TCR)为您提供安全独享、高性能的容器镜像托管分发服务。您可同时在全球多个地域创建独享实例,以实现容器镜像的就近拉取,降低拉取时间,节约带宽成本。TCR 提供细颗粒度的权限管理及访问控制,保障您的数据安全。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档