在Spring Boot开发中,单元测试是保障代码质量的核心环节。本文将基于实际开发场景,手把手教你如何快速实现分层测试、模拟依赖、编写高效断言,并分享最佳实践!
一、5分钟环境搭建
-
添加依赖
在pom.xml
中引入spring-boot-starter-test
,默认集成JUnit 5、Mockito、AssertJ等工具:<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency>
-
测试类模板
测试类通常放在src/test/java
目录,命名规范为被测试类名 + Test
。基础模板如下:@SpringBootTest // 加载Spring上下文(适合集成测试) @ExtendWith(SpringExtension.class) // JUnit 5注解 class UserServiceTest { @Autowired private UserService userService; // 测试方法... }
二、分层测试:精准覆盖每一层
1. Service层测试:Mock依赖
场景:测试业务逻辑,隔离外部依赖(如数据库、第三方接口)。
工具:@MockBean
模拟Spring管理的Bean。
@SpringBootTest
class UserServiceTest {
@Autowired
private UserService userService;
@MockBean // 模拟Repository依赖
private UserRepository userRepository;
@Test
void testGetUserById() {
// 1. 定义Mock行为
when(userRepository.findById(1L)).thenReturn(Optional.of(new User("Alice")));
// 2. 调用方法
User user = userService.getUserById(1L);
// 3. 断言结果
assertThat(user.getName()).isEqualTo("Alice");
}
}
2. Controller层测试:MockMvc模拟HTTP请求
工具:@WebMvcTest
仅加载Web层组件,搭配MockMvc
模拟请求。
@WebMvcTest(UserController.class) // 仅初始化Web层
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void testGetUser() throws Exception {
when(userService.getUserById(1L)).thenReturn(new User("Alice"));
// 模拟GET请求并验证响应
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Alice"));
}
}
3. 持久层测试:真实数据库操作
工具:@DataJpaTest
(JPA)或@DataMongoTest
(MongoDB)。
@DataJpaTest // 仅加载JPA组件,默认使用H2内存数据库
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void testSaveUser() {
User user = new User("Bob");
User savedUser = userRepository.save(user);
// 验证ID自动生成
assertThat(savedUser.getId()).isNotNull();
}
}
三、测试进阶技巧
1. 参数化测试:覆盖多场景
使用@ParameterizedTest
快速测试多组输入:
@ParameterizedTest
@ValueSource(ints = {1, 3, 5, -1}) // 测试奇数和边界值
void testIsOdd(int number) {
assertTrue(number % 2 != 0);
}
2. 测试生命周期控制
• @BeforeEach
:每个测试方法前执行(如初始化数据)。
• @AfterEach
:每个测试方法后执行(如清理数据库)。
@BeforeEach
void setup() {
userRepository.deleteAll();
userRepository.save(new User("TestUser"));
}
3. 测试专用配置
通过@TestPropertySource
加载测试配置文件:
@SpringBootTest
@TestPropertySource(locations = "classpath:test.properties")
class MyTest {
// 使用test.properties中的配置
}
四、最佳实践与避坑指南
-
分层策略
• 单元测试:聚焦单一类,用@MockBean
隔离外部依赖。• 集成测试:使用
@SpringBootTest
验证组件交互。• Web层测试:优先用
@WebMvcTest
而非启动完整应用。 -
断言工具选择
• AssertJ(推荐):链式断言更直观。assertThat(userList) .hasSize(3) .extracting("name") .contains("Alice", "Bob");
-
环境隔离
• 使用H2内存数据库替代生产库。• 用
@MockBean
模拟外部服务(如支付接口)。 -
测试数据管理
• @Sql注解:运行前执行SQL脚本初始化数据。@Test @Sql("/init-user-data.sql") void testUserCount() { assertThat(userRepository.count()).isEqualTo(5); }
五、快速运行测试
• IDE操作:右键测试类 → Run as JUnit Test
。
• 命令行运行:
mvn test # Maven
./gradlew test # Gradle
总结
单元测试不是负担,而是高效开发的基石。通过分层测试、精准Mock和高效断言,可以大幅提升代码可靠性。立即动手,为你的Spring Boot项目加上“安全锁”吧!
新时代农民工