JUnit 5 使用指南
可以给我一个🆓的大拇哥吗?👍😚
JUnit 5 是 Java 中最流行的单元测试框架之一,它引入了许多新特性,使得编写和运行测试更加灵活和强大。
1. 环境准备
1.1 添加依赖
Maven 项目:
在 pom.xml
中添加以下依赖:
<dependencies>
<!-- JUnit 5 核心依赖 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<!-- JUnit 5 测试引擎 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Gradle 项目:
在 build.gradle
中添加以下依赖:
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.10.0'
}
1.2 配置 IDE
确保你的 IDE(如 IntelliJ IDEA 或 Eclipse)支持 JUnit 5。大多数现代 IDE 都默认支持 JUnit 5。
2. 编写第一个测试
2.1 创建一个简单的类
假设我们有一个简单的 Calculator
类,用于实现加法和减法:
public class Calculator {
// 实现加法方法
public int add(int a, int b) {
return a + b;
}
// 实现减法方法
public int subtract(int a, int b) {
return a - b;
}
}
2.2 编写测试类
在 src/test/java
目录下创建一个测试类 CalculatorTest
:
// 导入 JUnit 5 的 Test 注解
import org.junit.jupiter.api.Test;
// 导入断言方法 assertEquals,用于比较期望值与实际值
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CalculatorTest {
@Test // 标记该方法为测试方法
public void testAdd() {
// 创建 Calculator 实例
Calculator calculator = new Calculator();
// 调用加法方法,并将结果保存到 result 中
int result = calculator.add(2, 3);
// 断言 2 + 3 的结果应为 5,若不相等则输出提示信息
assertEquals(5, result, "2 + 3 应该等于 5");
}
@Test // 标记该方法为测试方法
public void testSubtract() {
// 创建 Calculator 实例
Calculator calculator = new Calculator();
// 调用减法方法,并将结果保存到 result 中
int result = calculator.subtract(5, 3);
// 断言 5 - 3 的结果应为 2,若不相等则输出提示信息
assertEquals(2, result, "5 - 3 应该等于 2");
}
}
2.3 运行测试
在 IDE 中右键点击测试类或方法,选择“Run”即可运行测试。如果所有测试通过,你会看到绿色的成功提示。
3. JUnit 5 的核心注解
JUnit 5 提供了许多注解来支持测试的编写和运行。以下是一些常用的注解:
3.1 @Test
标记一个方法为测试方法。
@Test
public void testMethod() {
// 测试代码
}
3.2 @BeforeEach
和 @AfterEach
@BeforeEach
:在每个测试方法之前运行。@AfterEach
:在每个测试方法之后运行。
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;
public class ExampleTest {
@BeforeEach
public void setUp() {
// 每个测试方法执行前都会运行此方法
System.out.println("测试开始前执行");
}
@AfterEach
public void tearDown() {
// 每个测试方法执行后都会运行此方法
System.out.println("测试结束后执行");
}
}
3.3 @BeforeAll
和 @AfterAll
@BeforeAll
:在所有测试方法之前运行(方法必须为静态)。@AfterAll
:在所有测试方法之后运行(方法必须为静态)。
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.AfterAll;
public class ExampleTest {
@BeforeAll
public static void init() {
// 所有测试方法执行前运行,仅执行一次
System.out.println("所有测试开始前执行");
}
@AfterAll
public static void cleanup() {
// 所有测试方法执行后运行,仅执行一次
System.out.println("所有测试结束后执行");
}
}
3.4 @DisplayName
为测试类或方法指定一个易读的名称。
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("计算器测试")
public class CalculatorTest {
@Test
@DisplayName("测试加法")
public void testAdd() {
// 测试代码
}
}
4. 断言(Assertions)
JUnit 5 提供了丰富的断言方法,用于验证测试结果是否符合预期。
4.1 常用断言方法
assertEquals(expected, actual)
:验证两个值是否相等。assertNotEquals(unexpected, actual)
:验证两个值是否不相等。assertTrue(condition)
:验证条件是否为真。assertFalse(condition)
:验证条件是否为假。assertNull(actual)
:验证值是否为null
。assertNotNull(actual)
:验证值是否不为null
。
示例:
// 导入所有断言方法
import static org.junit.jupiter.api.Assertions.*;
@Test
public void testAssertions() {
int result = 5;
// 断言结果等于 5
assertEquals(5, result, "结果应该等于 5");
// 断言结果大于 0
assertTrue(result > 0, "结果应该大于 0");
// 断言结果不为 null
assertNotNull(result, "结果不应该为 null");
}
5. 参数化测试
JUnit 5 支持参数化测试,允许你使用不同的输入参数运行同一个测试方法。
5.1 使用 @ParameterizedTest
和 @ValueSource
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class ParameterizedTestExample {
@ParameterizedTest // 标记这是一个参数化测试方法
@ValueSource(ints = {1, 3, 5, 7}) // 提供一组整数作为参数
void testIsOdd(int number) {
// 断言每个传入的 number 应为奇数
assertTrue(number % 2 != 0, number + " 应该是奇数");
}
}
5.2 使用 @CsvSource
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class CsvSourceTest {
@ParameterizedTest // 标记这是一个参数化测试方法
@CsvSource({
"2, 3, 5", // 传入 a=2, b=3, expected=5
"10, 20, 30" // 传入 a=10, b=20, expected=30
})
void testAdd(int a, int b, int expected) {
// 创建 Calculator 实例
Calculator calculator = new Calculator();
// 断言计算结果是否符合预期
assertEquals(expected, calculator.add(a, b));
}
}
5.3 使用 @MethodSource
1. 定义
@MethodSource
是 JUnit 5 提供的一个注解,用于为参数化测试提供数据。它允许你通过一个方法来提供测试数据,而不是直接在注解中写死数据。
作用:
- 动态提供数据:通过一个方法动态生成测试数据,而不是直接在注解中写死数据。
- 灵活性:可以更灵活地生成测试数据,支持复杂的测试场景。
2. 示例代码
假设我们有一个 Calculator 类,我们想测试它的 add 方法。我们使用 @MethodSource
提供测试数据。
Calculator 类
public class Calculator {
// 实现加法方法
public int add(int a, int b) {
return a + b;
}
}
测试类
// 导入 @MethodSource 注解(注意:这里有两个 MethodSource,一个来自 org.junit.jupiter.api,一个来自参数化包)
import org.junit.jupiter.api.MethodSource;
import org.junit.jupiter.params.ParameterizedTest;
// 导入 Arguments 类,用于封装一组测试参数
import org.junit.jupiter.params.provider.Arguments;
// 同时导入 @MethodSource 注解(用于参数化测试数据提供器)
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.stream.Stream;
public class CalculatorTest {
@ParameterizedTest // 标记这是一个参数化测试方法,允许为同一个测试方法提供多组输入数据
@MethodSource("provideDataForAdd") // 指定 provideDataForAdd 方法作为数据提供器
void testAdd(int a, int b, int expected) {
// 创建 Calculator 实例
Calculator calculator = new Calculator();
// 断言计算结果是否符合预期
assertEquals(expected, calculator.add(a, b));
}
// 数据提供方法,返回 Stream<Arguments>,每组数据表示一组测试输入
static Stream<Arguments> provideDataForAdd() {
return Stream.of(
// Arguments.of 用于创建一组输入数据
Arguments.of(2, 3, 5),
Arguments.of(10, 20, 30),
Arguments.of(-1, 1, 0)
);
}
}
3. 逐行注释
3.1 @ParameterizedTest
@ParameterizedTest
- 作用:标记这是一个参数化测试方法,允许为同一个测试方法提供多组输入数据。
3.2 @MethodSource
@MethodSource("provideDataForAdd")
- 作用:指定一个方法作为数据提供器,该方法返回一个
Stream<Arguments>
,每组数据表示一组输入。
3.3 测试方法
void testAdd(int a, int b, int expected) {
Calculator calculator = new Calculator();
assertEquals(expected, calculator.add(a, b));
}
- 作用:测试
Calculator
的add
方法,验证计算结果是否符合预期。 - 参数说明:
int a, int b
:传入的两个操作数。int expected
:预期结果。
3.4 数据提供方法
static Stream<Arguments> provideDataForAdd() {
return Stream.of(
Arguments.of(2, 3, 5),
Arguments.of(10, 20, 30),
Arguments.of(-1, 1, 0)
);
}
- 作用:提供测试数据,每组数据表示一组输入。
- 说明:
- 使用
Stream.of
创建一个数据流。 - 每个
Arguments.of(...)
表示一组测试输入。
- 使用
可以给我一个🆓的大拇哥吗?👍😚