【SpringBoot深入浅出系列】SpringBoot之集成JUnit5进行单元测试

举报
奔跑吧邓邓子 发表于 2022/04/22 23:48:21 2022/04/22
【摘要】 一、JUnit 5 是什么?与以前版本的 JUnit 不同,JUnit 5 由来自三个不同子项目的几个不同模块组成。JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage JUnit Platform是启动 JVM 上测试框架的基础。它还定义了用于开发在平台上运行的测试框架的 API。此外,该平台还提供了一个控制台启动器,用于从命令...

一、JUnit 5 是什么?

与以前版本的 JUnit 不同,JUnit 5 由来自三个不同子项目的几个不同模块组成。

JUnit 5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

JUnit Platform

是启动 JVM 上测试框架的基础。它还定义了用于开发在平台上运行的测试框架的 API。此外,该平台还提供了一个控制台启动器,用于从命令行启动平台,并提供 JUnit 平台套件引擎,用于使用平台上的一个或多个测试引擎运行自定义测试套件。

JUnit Jupiter

是新的编程模型和扩展模型的组合,用于在 JUnit 5 中编写测试和扩展。Jupiter 子项目提供了一个用于在平台上运行基于 Jupiter 的测试。

JUnit Vintage

提供了一个用于在平台上运行基于 JUnit 3 和 JUnit 4 的测试。

二、为什么使用 JUnit 5 ?

至少有以下优点:

  1. JUnit 5 利用了Java 8 或更高版本的特性,例如 lambda 函数,使测试更强大,更容易维护。
  2. JUnit 5 可以同时使用多个扩展,可以轻松地将 Spring 扩展与其他扩展(如自定义扩展)结合起来,包容性强,可以接入其他的测试引擎。
  3. 功能更强大,提供了新的断言机制、参数化测试、重复性测试等新功能。

从 JUnit 4 切换到 JUnit 5 非常简单,步骤如下:

  1. 将库和构建系统从 JUnit 4 更新到 JUnit 5。确保在测试运行时路径中包含 junit-vintage-engine ,以允许现有的测试执行。
  2. 使用新的 JUnit 5 构造开始构建新的测试。

三、JUnit 4 和 JUnit 5 的区别

1.导入

JUnit 5 使用新的 org.junit.jupiter 包,Junit 4 使用的是 org.junit 包。

2.@Test 注解

@Test 注解不再有参数,每个参数都被移到了一个函数中。

3.超时写法发生变化

4.其它注解

@Before 变成了 @BeforeEach
@After 变成了 @AfterEach
@BeforeClass 变成了 @BeforeAll
@AfterClass 变成了 @AfterAll
@Ignore 变成了 @Disabled
@Category 变成了 @Tag
@Rule 和 @ClassRule 没有了,用 @ExtendWith 和 @RegisterExtension 代替

5.断言

JUnit 5 断言在 org.junit.jupiter.api.Assertions 中。大多数常见的断言,如 assertEquals() 和 assertNotNull(),和以前有所不同,错误信息放在了最后一个参数,例如:
assertEquals(“my message”,1,2) 变为 assertEquals(1,2,”my message”)

大多数断言现在接受一个构造错误信息的lambda,只有当断言失败时才会被调用。

6.假设

假设已被移至 org.junit.jupiter.api.Assumptions。
同样的假设也存在,但它们支持 BooleanSupplier 以及 Hamcrest 匹配器(http://hamcrest.org/)来匹配条件。Lambdas(类型为 Executable)可以用来在条件满足时执行代码。

7.扩展

在 JUnit 4中,自定义框架通常意味着使用 @RunWith 注释来指定一个自定义的运行器。使用多个运行器是有问题的,通常需要链式或使用 @Rule。在 JUnit 5 中已经得到了简化和改进。

四、创建项目集成 JUnit 5 进行单元测试

1.项目说明

新建 Spring Initializr 项目 junit,项目下新建 entity、controller 类。项目创建示例说明 JUnit 5 的使用。
项目目录结构:
在这里插入图片描述

2.创建 Spring Initializr 项目 junit

在这里插入图片描述

(1)添加依赖

添加依赖,如果已按截图操作,pom.xml 还需引入 Junit 5 依赖:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
    <exclusions>
        <exclusion>
            <groupId>org.junit.vintage</groupId>
            <artifactId>junit-vintage-engine</artifactId>
        </exclusion>
    </exclusions>
</dependency>

完整的 pom.xml 文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.chaoyue</groupId>
    <artifactId>junit</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>junit</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

(2)添加配置

application.yml 文件中添加如下配置:

server:
  port: 8080

(3)新建实体类 User

为减少不必要的代码,引入 lombok 依赖。实体类代码如下:

package com.chaoyue.junit.entity;

import lombok.Data;

@Data
public class User {
//    @TableId(type = IdType.AUTO)
    private Long id; // id
    private String username; // 用户名
    private String password; // 密码
}

(4)新建控制类 LoginController

package com.chaoyue.junit.controller;

import com.chaoyue.junit.entity.User;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/user")
public class LoginController {

    @GetMapping("getUserInfo")
    public String getUserInfo() {

        // 获取用户信息
        User userInfo = new User();
        userInfo.setId(1L);
        userInfo.setUsername("admin");
        userInfo.setPassword("123456");
        return userInfo.toString();

    }

}

3.创建 Junit 5 测试示例

(1)创建测试类 LoginControllerTest

在LoginController 类上使用快捷键 ctrl + shift + t 打开弹窗: 在这里插入图片描述
点击【Create New Test…】创建测试类:
在这里插入图片描述

(2)添加注解

测试类添加注解 @SpringBootTest:

package com.chaoyue.junit.controller;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import static org.junit.jupiter.api.Assertions.*;

@SpringBootTest
class LoginControllerTest {

    @BeforeEach
    void setUp() {
    }

    @AfterEach
    void tearDown() {
    }

    @Test
    void getUserInfo() {
    }
}

(3)测试示例

①断言:判断条件是否为 true 或 false

    /**
     * assertTrue、assertFalse 判断条件是否为 true 或 false
     */
    @Test
    @DisplayName("测试断言 assertTrue、assertTrue")
    void testTrue() {
        assertTrue(1 > 2 );
//        assertFalse(1 > 2 );
    }

②断言:判断两个值是否相等

    /**
     * assertEquals、assertNotEquals 判断两个值是否相等
     */
    @Test
    @DisplayName("测试断言 assertEquals、assertNotEquals")
    void testEquals() {
        assertEquals(1, 2 );
//        assertNotEquals(1, 2 );
    }

③断言:判断条件是否为 null 或 not null

    /**
     * assertNull、assertNotNull 判断条件是否为 null 或 not null
     */
    @Test
    @DisplayName("测试断言 assertNull、assertNotNull")
    void testNotNull() {
        assertNotNull(new Object());
//        assertNull(new Object());
    }

④断言:判断断言是否超时

/**
 * assertTimeout 判断断言是否超时
 */
@Test
@DisplayName("测试断言 assertTimeout")
void testTimeout() {
    String result = assertTimeout(ofSeconds(2),() -> {
        Thread.sleep(1000);
        return "未超时";
    });
    System.out.println(result);
}

⑤断言:组合断言

/**
 * assertAll 组合断言,当内部所有断言都正确执行才算通过
 */
@Test
@DisplayName("测试组合断言")
void testTAll() {
    assertAll("测试组合断言",
            () -> {
                assertTrue(1 < 2, "断言1");
            },
            () -> {
                assertNotNull(new Object(), "断言2");
            },
            () -> {
                assertEquals(1,1);
            }
    );
}

⑥重复测试

/**
 * RepeatedTest 重复测试
 */
@RepeatedTest(3)
@DisplayName("重复测试")
void testRepeat() {
    System.out.println("重复测试");
}

⑦参数化测试

/**
 * ParameterizedTest 参数化测试
 */
@ParameterizedTest
@ValueSource(strings = {"参数1", "参数2", "参数3"})
@DisplayName("参数化测试")
void testParam(String param) {
    assertEquals(param, "参数1");
    System.out.println(param);
}

PS:JUnit 5 官网:https://junit.org/junit5/

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。