@SpringBootTest
详解及详细代码示例
@SpringBootTest
是 Spring Boot 提供的核心测试注解,用于启动 完整的 Spring 应用上下文,支持集成测试(Integration Test)。它通过加载 ApplicationContext
,验证组件间的协作,适用于需要完整依赖链的测试场景。
一、核心功能
-
启动完整应用上下文
- 加载
@SpringBootApplication
主配置类。 - 支持
@Autowired
注入 Bean。
- 加载
-
配置环境隔离
- 通过
properties
属性覆盖配置。 - 支持随机端口(
webEnvironment = WebEnvironment.RANDOM_PORT
)。
- 通过
-
切片测试支持
- 结合
@AutoConfigureMockMvc
、@AutoConfigureDataJpa
等实现分层测试。
- 结合
-
测试切片(Test Slices)
- 仅加载部分配置(如
@WebMvcTest
、@DataJpaTest
),提升测试速度。
- 仅加载部分配置(如
二、与 @Test
注解的区别
特性 | @SpringBootTest | @Test (JUnit 注解) |
---|---|---|
上下文加载 | 启动完整 Spring 容器 | 无 |
依赖注入 | 支持 @Autowired | 无 |
执行速度 | 较慢(完整上下文) | 快(无容器) |
适用场景 | 集成测试(需完整依赖链) | 单元测试(无依赖或模拟依赖) |
三、详细代码示例
3.1 基础集成测试
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest
class UserServiceIntegrationTest {
@Autowired
private UserRepository userRepository;
@Autowired
private UserService userService;
@Test
void testUserCreation() {
// 1. 准备测试数据
User newUser = new User(0, "Alice");
// 2. 执行测试方法
User savedUser = userService.createUser(newUser);
// 3. 验证结果
assertNotNull(savedUser.getId());
assertEquals("Alice", savedUser.getName());
// 4. 验证数据库操作
User dbUser = userRepository.findById(savedUser.getId()).orElseThrow();
assertEquals("Alice", dbUser.getName());
}
}
// 被测服务
@Service
class UserService {
private final UserRepository userRepository;
@Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User createUser(User user) {
return userRepository.save(user);
}
}
// 数据库接口
interface UserRepository extends JpaRepository<User, Integer> {}
// 实体类
@Entity
record User(@Id @GeneratedValue(strategy = GenerationType.IDENTITY) int id, String name) {}
3.2 配置环境隔离
@SpringBootTest(properties = {
"app.env=test",
"spring.datasource.url=jdbc:h2:mem:testdb"
})
class ConfigOverrideTest {
@Autowired
private AppConfig appConfig;
@Test
void testConfigOverride() {
assertEquals("test", appConfig.getEnv());
}
}
@Configuration
@ConfigurationProperties(prefix = "app")
class AppConfig {
private String env;
// Getter/Setter
}
3.3 随机端口测试
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class WebIntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void testApiEndpoint() {
// 1. 发送 GET 请求
ResponseEntity<String> response = restTemplate.getForEntity("/api/users", String.class);
// 2. 验证状态码和响应体
assertEquals(200, response.getStatusCodeValue());
assertTrue(response.getBody().contains("Alice"));
}
}
3.4 切片测试(Web 层)
@WebMvcTest(UserController.class)
@AutoConfigureMockMvc
class WebSliceTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void testGetUser() throws Exception {
// 1. 模拟依赖行为
User mockUser = new User(1, "Alice");
when(userService.getUserById(1)).thenReturn(mockUser);
// 2. 发送请求并验证响应
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Alice"));
}
}
@RestController
@RequestMapping("/api/users")
class UserController {
private final UserService userService;
@Autowired
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public User getUser(@PathVariable int id) {
return userService.getUserById(id);
}
}
3.5 事务回滚测试
@SpringBootTest
@Transactional
@Rollback
class TransactionalTest {
@Autowired
private UserRepository userRepository;
@Test
void testTransactionRollback() {
// 1. 创建用户
User user = new User(0, "Bob");
userRepository.save(user);
// 2. 验证数据库状态(事务未提交)
assertFalse(userRepository.findById(user.getId()).isPresent());
}
}
四、高级配置
4.1 指定启动类
@SpringBootTest(classes = MyCustomApplication.class)
class CustomContextTest {}
4.2 排除自动配置
@SpringBootTest(excludeAutoConfiguration = SecurityAutoConfiguration.class)
class NoSecurityTest {}
4.3 动态属性覆盖
@TestPropertySource(properties = "app.feature.toggle=true")
@SpringBootTest
class FeatureToggleTest {}
五、最佳实践
-
分层测试策略
- 单元测试(
@Test
+ Mockito)→ 切片测试(@WebMvcTest
)→ 集成测试(@SpringBootTest
)。
- 单元测试(
-
避免全量测试
- 仅在需要完整上下文时使用
@SpringBootTest
,优先使用切片测试提升速度。
- 仅在需要完整上下文时使用
-
测试数据管理
- 使用
@Sql
注解初始化测试数据:@Sql("/test-data.sql") @SpringBootTest class DataDrivenTest {}
- 使用
-
并行测试
- 配置
spring.main.web-application-type=none
禁用 Web 环境加速测试。
- 配置
通过 @SpringBootTest
,开发者可以编写覆盖完整业务流的集成测试,确保系统各组件协同工作。结合切片测试和 Mockito,可实现高效的测试金字塔策略。