乐趣区

关于java:JUnit-5简明教程

概述

写测试用例对于开发来说有 2 点益处,一是开发阶段写完的性能能够疾速验证,第二就是在前期需要变动或批改 BUG 后能够疾速测试以后改变是否带来其它问题。上面就理解一下 Junit5 写测试用例。

筹备

创立一个 maven 我的项目

mkdir junit5-tutorial
cd junit5-tutorial

mkdir -p src/main/java
mkdir -p src/test/java

mkdir -p src/main/resources
mkdir -p src/test/resources

# 编写 pom.xml
vi pom.xml

增加依赖

  • 引入第三方断言库 assertj
  • 反对 json 测试
  • 反对 xml 测试

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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example.xxx</groupId>
    <artifactId>junit5-tutorial</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>junit5-tutorial</name>

    <url>https://www.xxx.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
    </properties>

    <build>
        <pluginManagement>
            <plugins>
                <!-- 在这里申明的目标是应用指定的版本 -->
                <!-- 执行测试用例工作的插件,默认绑定 test 生命周期的 test 阶段 -->
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M6</version>
                </plugin>
                <!-- 用来执行编译工作的插件,默认绑定 default 生命周期 compile 阶段 -->
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.10.1</version>
                </plugin>
            </plugins>
        </pluginManagement>

    </build>

    <dependencyManagement>
        <dependencies>
            <!-- XML Unit - Dependency Management -->
            <dependency>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy</artifactId>
                <version>1.12.10</version>
            </dependency>
            <dependency>
                <groupId>net.bytebuddy</groupId>
                <artifactId>byte-buddy-agent</artifactId>
                <version>1.12.10</version>
                <scope>test</scope>
            </dependency>

            <!-- Mockito Dependency -->
            <dependency>
                <groupId>org.mockito</groupId>
                <artifactId>mockito-junit-jupiter</artifactId>
                <version>4.5.1</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <version>3.22.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.github.classgraph</groupId>
            <artifactId>classgraph</artifactId>
            <version>4.8.146</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>5.8.2</version>
        </dependency>

        <!-- JSON Unit - Dependencies -->
        <dependency>
            <groupId>net.javacrumbs.json-unit</groupId>
            <artifactId>json-unit-assertj</artifactId>
            <version>2.33.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.13.2.2</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.datatype</groupId>
            <artifactId>jackson-datatype-jsr310</artifactId>
            <version>2.13.2</version>
        </dependency>

        <!-- XML Unit - Dependencies -->
        <dependency>
            <groupId>org.xmlunit</groupId>
            <artifactId>xmlunit-assertj</artifactId>
            <version>2.9.0</version>
            <scope>test</scope>
        </dependency>

    </dependencies>
</project>

创立一个 User

public record User(String name, Integer age, Boolean blocked, LocalDate birthDate) {}

测试

测试用例命名最佳实际

首先测试类名应该以 Test 结尾,测试用例名称最好听从以下规定

  1. 测试名称应表白特定要求
  2. 测试名称应蕴含预期的输出或预期的后果
  3. 测试名称应以陈说的模式

具体参考:https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html

断言

@Test
@DisplayName("User should be at least 18")
void user_should_be_at_least_18() {
    // junit5 的断言
    assertTrue(user.age() >= 18);
    // assertj 的断言
    assertThat(user.age()).isGreaterThanOrEqualTo(18);
}

显示名称

测试类和测试方法能够申明自定义显示名称,能够应用空格、特殊字符、甚至 emojis 表情符号,这些名称会在 runner 和测试报告中显示。

参数化测试

参数化测试能够用不同的参数屡次运行测试。它们和一般的 @Test 办法一样申明,然而应用 @ParameterizedTest 注解。还必须申明至多一个将为每次调用提供参数的来

应用 @ValueSource 来指定参数起源

它能够指定一个原生类型的数组,并且只能为每次调用提供一个参数

@ParameterizedTest
@ValueSource(ints = {20, 50, 80})
void test_value_source(int age) {assertThat(age).isGreaterThanOrEqualTo(18);
}

读取 CSV 文件内容作为参数起源

它能够让你应用 classpath 中的 csv 文件。csv 文件中的每一行都会导致参数测试的一次调用

src/test/resources/friends.csv

name,age
lisa,20
hans,30
hanna,40
@ParameterizedTest
@CsvFileSource(resources = "/friends.csv", numLinesToSkip = 1)
void test_value_source_by_csv_file_source(String name, int age) {assertThat(age).isGreaterThanOrEqualTo(18);
}

标签

咱们能够给测试类或测试用例下面通过 @Tag 加标签,执行测试的时候能够指定标签,从而达到为测试用例分组的目标。
上面就给测试类打上一个 integration 的标签

@Tag("integration")
class User01Test {// ...}

能够应用如下命令来指定要执行的测试用例:

mvn test -Dgroups="integration"

左侧只执行了 Running com.example.xxx.User01Test 一个测试类,右侧则执行了 3 个

总结

本文介绍了如何应用 Junit5 写测试用例。

参考

  1. Unit test naming best practices Unit test naming best practices – Stack Overflow
  2. https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html
  3. AssertJ Homepage https://assertj.github.io/doc/
  4. Gradle: https://stackoverflow.com/a/64986861
  5. https://junit.org/junit5/docs/current/user-guide/#running-tests-tag-expressions
  6. further reading
  7. JUnit 5 User Guide
  8. JUnit 5 中文文档 https://doczhcn.gitbook.io/junit5/
  9. AssertJ – fluent assertions java library
  10. Jupiter / JUnit 5 – Testcontainers
  11. awaitility/awaitility: Awaitility is a small Java DSL for synchronizing asynchronous operations (github.com)
退出移动版