本文目录导读:

在Java中实现单元测试,最主流的方式是使用 JUnit 框架(目前主要使用 JUnit 5,即 Jupiter),配合 Mockito 等 Mock 框架来处理外部依赖。
以下是一个从环境搭建到编写、运行测试的完整指南。
环境搭建
Maven 依赖 (pom.xml):
<dependencies>
<!-- JUnit 5 核心依赖 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>
<!-- Mockito 用于 Mock 对象 -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
</dependencies>
Gradle 依赖 (build.gradle):
dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
testImplementation 'org.mockito:mockito-core:5.6.0'
}
test {
useJUnitPlatform()
}
测试目录结构
Maven/Gradle 标准项目中,测试代码放在:
src/
├── main/java/ # 生产代码
└── test/java/ # 测试代码(包名通常与生产代码一致)
典型案例演示
假设有一个待测试的 Calculator 类和一个需要 Mock 外部依赖的 UserService 类。
待测试类 A:纯业务逻辑
// src/main/java/com/example/Calculator.java
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public int divide(int dividend, int divisor) {
if (divisor == 0) {
throw new IllegalArgumentException("Divisor cannot be zero");
}
return dividend / divisor;
}
}
待测试类 B:依赖外部服务
// src/main/java/com/example/UserService.java
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public String getUserNameById(int id) {
User user = userRepository.findById(id);
if (user == null) {
throw new RuntimeException("User not found");
}
return user.getName();
}
}
interface UserRepository {
User findById(int id);
}
class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() { return name; }
}
编写单元测试
测试 A:测试纯逻辑(无依赖)
// src/test/java/com/example/CalculatorTest.java
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class CalculatorTest {
@Test
void testAdd() {
// 1. 准备(Arrange)
Calculator calc = new Calculator();
// 2. 执行(Act)
int result = calc.add(3, 5);
// 3. 断言(Assert)
assertEquals(8, result);
}
@Test
void testDivide() {
Calculator calc = new Calculator();
assertEquals(2, calc.divide(10, 5));
}
@Test
void testDivideByZero() {
Calculator calc = new Calculator();
// 验证抛出指定异常
assertThrows(IllegalArgumentException.class,
() -> calc.divide(10, 0));
}
}
测试 B:测试有外部依赖的类(使用 Mockito)
// src/test/java/com/example/UserServiceTest.java
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
// 启用 Mockito 扩展(JUnit 5 方式)
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository; // 创建 Mock 对象
@Test
void testGetUserNameById_UserExists() {
// 1. 准备(Arrange)
// 定义 Mock 行为:当 findById(1) 被调用时,返回一个 User 对象
when(userRepository.findById(1)).thenReturn(new User(1, "Alice"));
UserService userService = new UserService(userRepository);
// 2. 执行(Act)
String name = userService.getUserNameById(1);
// 3. 断言(Assert)
assertEquals("Alice", name);
// 4. 验证(Verify):确保 findById 确实被调用了一次
verify(userRepository, times(1)).findById(1);
}
@Test
void testGetUserNameById_UserNotFound() {
// 准备:让 findById 返回 null
when(userRepository.findById(anyInt())).thenReturn(null);
UserService userService = new UserService(userRepository);
// 执行 + 断言:期望抛出 RuntimeException
assertThrows(RuntimeException.class,
() -> userService.getUserNameById(999));
}
}
运行测试
IDE 内运行
- IntelliJ IDEA:在测试类或方法左侧点击绿色三角形 ▶ 直接运行。
- Eclipse:右键测试类 →
Run As→JUnit Test。
Maven 命令行
mvn test
Gradle 命令行
gradle test
常见注解速查表
| 注解 | 说明 |
|---|---|
@Test |
标记一个测试方法 |
@BeforeEach |
在每个测试方法前执行(初始化) |
@AfterEach |
在每个测试方法后执行(清理) |
@BeforeAll |
在所有测试方法前执行一次(静态方法) |
@AfterAll |
在所有测试方法后执行一次(静态方法) |
@DisplayName("描述") |
为测试类或方法添加中文/描述性名称 |
@ExtendWith(...) |
注册扩展,如 MockitoExtension |
重要断言方法:
assertEquals(expected, actual):判断相等assertTrue(condition):判断为真assertThrows(ExceptionClass, executable):判断抛异常assertNotNull(object):判断不为 null
关键原则
- 独立性:每个测试方法不要依赖其他测试的结果。
- 可重复:每次运行结果一致(避免依赖随机数据、当前时间、网络等)。
- 单一职责:一个测试方法只测试一个行为或条件。
- 命名清晰:方法名最好能说明“在什么条件下,期望什么结果”,
testDivide_shouldThrowException_whenDivisorIsZero
- 使用 Mock:对外部服务、数据库、文件系统一律 Mock,测试只关注当前类的逻辑。
- 纯逻辑:直接
new目标类,调用方法,用assertEquals等断言。 - 依赖外部:用
@Mock创建 Mock 对象,用when().thenReturn()定义行为。 - 运行方式:IDE 或 Maven/Gradle 命令行。
- 行业标配:JUnit 5 + Mockito。
按照上述步骤和模板,你就可以在 Java 项目中系统化地编写单元测试了。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播