Spring Boot测试类的使用参考
1. 集成测试概述
集成测试是在完整的Spring应用上下文中测试应用组件之间的交互。与单元测试不同,集成测试会启动Spring容器并加载所有配置的Bean。
2. 依赖配置
2.1 Maven依赖
<!-- Spring Boot测试核心依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- 如果需要测试Web接口,需添加此依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
2.2 Gradle依赖
// Spring Boot测试核心依赖
testImplementation 'org.springframework.boot:spring-boot-starter-test'
// Web接口测试依赖
testImplementation 'org.springframework.boot:spring-boot-starter-web'
3. 核心注解使用
3.1 @SpringBootTest注解
@SpringBootTest是Spring Boot集成测试的核心注解,用于启动完整的Spring应用上下文。
基础使用方式
@SpringBootTest
public class MyIntegrationTest {
// 测试代码
}
什么时候需要指定启动类?
在以下情况下需要在@SpringBootTest中指定classes属性:
- 多模块项目:测试类与Spring Boot启动类不在同一模块中
- 启动类不在默认包结构:测试类无法自动扫描到启动类
- 自定义配置:需要使用特定的配置类启动测试
// 示例:指定启动类
@SpringBootTest(classes = MyApplication.class)
public class MyIntegrationTest {
// 测试代码
}
4. 不同版本组合的使用案例
4.1 Spring Boot < 2.2 + JUnit 4
基础集成测试
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class) // 必须显式指定运行器
@SpringBootTest(classes = MyApplication.class) // 指定启动类
public class MyServiceTest {
@Autowired
private MyService myService; // 注入实际的服务Bean
@Test
public void testService() {
// 调用实际的业务方法
String result = myService.process("test");
// 断言结果
assertEquals("expected", result);
}
}
Web接口集成测试
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = MyApplication.class)
@AutoConfigureMockMvc // 自动配置MockMvc
public class MyControllerTest {
@Autowired
private MockMvc mockMvc; // 注入MockMvc实例
@Test
public void testController() throws Exception {
mockMvc.perform(get("/api/test")) // 模拟HTTP请求
.andExpect(status().isOk()); // 验证响应状态
}
}
4.2 Spring Boot >= 2.2 + JUnit 5
基础集成测试
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = MyApplication.class) // 指定启动类
public class MyServiceTest {
@Autowired
private MyService myService; // 注入实际的服务Bean
@Test
public void testService() {
// 调用实际的业务方法
String result = myService.process("test");
// 断言结果
assertEquals("expected", result);
}
}
Web接口集成测试
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(classes = MyApplication.class)
@AutoConfigureMockMvc // 自动配置MockMvc
public class MyControllerTest {
@Autowired
private MockMvc mockMvc; // 注入MockMvc实例
@Test
public void testController() throws Exception {
mockMvc.perform(get("/api/test")) // 模拟HTTP请求
.andExpect(status().isOk()); // 验证响应状态
}
}
4.3 不指定启动类的情况
当测试类与Spring Boot启动类在同一模块且在同一包结构下时,可以不指定启动类:
// MyApplication.java 位于 com.example 包
package com.example;
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
// MyIntegrationTest.java 也位于 com.example 包
package com.example;
@SpringBootTest // 无需指定classes属性
public class MyIntegrationTest {
// 测试代码
}
5. 常见集成测试场景
5.1 数据库集成测试
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;
@SpringBootTest(classes = MyApplication.class)
@Transactional // 测试后自动回滚数据库操作
public class MyRepositoryTest {
@Autowired
private MyRepository repository; // 注入实际的Repository
@Test
public void testRepository() {
// 执行数据库操作
MyEntity entity = new MyEntity();
entity.setName("test");
MyEntity savedEntity = repository.save(entity);
// 验证结果
assertNotNull(savedEntity.getId());
assertEquals("test", savedEntity.getName());
}
}
5.2 外部服务集成测试
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest(classes = MyApplication.class)
public class MyExternalServiceTest {
@Autowired
private ExternalApiService externalApiService; // 注入调用外部API的服务
@Test
public void testExternalApi() {
// 调用外部API
String result = externalApiService.callExternalApi("test");
// 验证结果
assertNotNull(result);
}
}
6. 版本兼容性总结
| Spring Boot版本 | JUnit版本 | 核心注解 | 是否需要指定启动类 |
|---|---|---|---|
| < 2.2 | 4 | @RunWith(SpringRunner.class) @SpringBootTest | 多模块或非默认包结构时需要 |
| >= 2.2 | 5 | @SpringBootTest | 多模块或非默认包结构时需要 |
7. 最佳实践
- 最小化测试范围:虽然是集成测试,也应尽量减少测试类之间的依赖
- 使用@Transactional:对于数据库测试,使用@Transactional确保测试后数据回滚
- 合理指定启动类:仅在必要时指定classes属性,避免硬编码
- 分离测试环境配置:使用不同的配置文件(如application-test.yml)配置测试环境
- 使用切片测试:对于大型应用,可以使用@WebMvcTest、@DataJpaTest等切片测试注解,在不启动完整上下文的情况下进行集成测试
3万+

被折叠的 条评论
为什么被折叠?



