目前項目的目錄結構 簡要說明 因為項目是要分兩塊部署在不同的伺服器上的 task_producer是作為任務發佈者部署 task_customer是作為任務消費者 兩塊之前的消息通信的話,目前選用的是redis的隊列來進行的 消費者目前的代碼還沒有開始就暫時不展示了,下麵僅說明發佈者的目錄結構 cl ...
概述
寫測試用例對於開發來說有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結尾,測試用例名稱最好遵從以下規則
- 測試名稱應表達特定要求
- 測試名稱應包含預期的輸入或預期的結果
- 測試名稱應以陳述的形式
具體參考: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寫測試用例。
參考
- Unit test naming best practices Unit test naming best practices - Stack Overflow
- https://osherove.com/blog/2005/4/3/naming-standards-for-unit-tests.html
- AssertJ Homepage https://assertj.github.io/doc/
- Gradle: https://stackoverflow.com/a/64986861
- https://junit.org/junit5/docs/current/user-guide/#running-tests-tag-expressions
- further reading
- JUnit 5 User Guide
- JUnit 5 中文文檔 https://doczhcn.gitbook.io/junit5/
- AssertJ - fluent assertions java library
- Jupiter / JUnit 5 - Testcontainers
- awaitility/awaitility: Awaitility is a small Java DSL for synchronizing asynchronous operations (github.com)