> 技术文档 > Spring Boot 单元测试使用教程(仅供参考)_springboot test怎么用

Spring Boot 单元测试使用教程(仅供参考)_springboot test怎么用

        单元测试是软件开发中至关重要的一环,Spring Boot 提供了强大的测试支持。以下是 Spring Boot 单元测试的详细教程。


1. 准备工作

1.1 添加测试依赖

在 pom.xml 中添加测试相关依赖:

 org.springframework.boot spring-boot-starter-test test org.springframework spring-test test org.assertj assertj-core 3.24.2 test

1.2 测试类基本结构

import org.junit.jupiter.api.Test;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTestpublic class MyApplicationTests { @Test public void contextLoads() { // 测试Spring上下文是否正常加载 }}

2. 不同类型的测试

2.1 服务层测试

import org.junit.jupiter.api.Test;import org.mockito.InjectMocks;import org.mockito.Mock;import org.mockito.junit.jupiter.MockitoExtension;import org.junit.jupiter.api.extension.ExtendWith;import static org.mockito.Mockito.*;import static org.junit.jupiter.api.Assertions.*;@ExtendWith(MockitoExtension.class)public class UserServiceTest { @Mock private UserRepository userRepository; @InjectMocks private UserService userService; @Test public void testGetUserById() { // 准备测试数据 User mockUser = new User(1L, \"test@example.com\", \"Test User\"); // 定义mock行为 when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser)); // 调用测试方法 User result = userService.getUserById(1L); // 验证结果 assertEquals(\"Test User\", result.getName()); verify(userRepository, times(1)).findById(1L); }}

2.2 控制器层测试

使用MockMvc
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.*;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;@SpringBootTest@AutoConfigureMockMvcpublic class UserControllerTest { @Autowired private MockMvc mockMvc; @Test public void testGetUser() throws Exception { mockMvc.perform(get(\"/api/users/1\"))  .andExpect(status().isOk())  .andExpect(jsonPath(\"$.name\").value(\"Test User\")); }}
使用WebTestClient (WebFlux)
import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.web.reactive.server.WebTestClient;@SpringBootTest@AutoConfigureWebTestClientpublic class UserControllerWebTestClientTest { @Autowired private WebTestClient webTestClient; @Test public void testGetUser() { webTestClient.get().uri(\"/api/users/1\")  .exchange()  .expectStatus().isOk()  .expectBody()  .jsonPath(\"$.name\").isEqualTo(\"Test User\"); }}

2.3 数据库测试

使用@DataJpaTest
import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;import static org.assertj.core.api.Assertions.*;@DataJpaTestpublic class UserRepositoryTest { @Autowired private TestEntityManager entityManager; @Autowired private UserRepository userRepository; @Test public void testFindByEmail() { // 准备测试数据 User user = new User(\"test@example.com\", \"Test User\"); entityManager.persist(user); entityManager.flush(); // 调用测试方法 User found = userRepository.findByEmail(user.getEmail()); // 验证结果 assertThat(found.getEmail()).isEqualTo(user.getEmail()); }}
使用@SpringBootTest + 测试数据库
import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.ActiveProfiles;import org.springframework.transaction.annotation.Transactional;import static org.junit.jupiter.api.Assertions.*;@SpringBootTest@ActiveProfiles(\"test\")@Transactionalpublic class UserServiceIntegrationTest { @Autowired private UserService userService; @Autowired private UserRepository userRepository; @Test public void testCreateUser() { User newUser = new User(\"new@example.com\", \"New User\"); User savedUser = userService.createUser(newUser); assertNotNull(savedUser.getId()); assertEquals(\"New User\", savedUser.getName()); User found = userRepository.findById(savedUser.getId()).orElse(null); assertEquals(\"New User\", found.getName()); }}

3. 常用测试技巧

3.1 参数化测试

import org.junit.jupiter.params.ParameterizedTest;import org.junit.jupiter.params.provider.ValueSource;import static org.junit.jupiter.api.Assertions.assertTrue;public class ParameterizedTests { @ParameterizedTest @ValueSource(strings = {\"racecar\", \"radar\", \"madam\"}) public void testPalindromes(String candidate) { assertTrue(StringUtils.isPalindrome(candidate)); }}

3.2 测试异常

import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.assertThrows;public class ExceptionTest { @Test public void testException() { UserService userService = new UserService(); assertThrows(UserNotFoundException.class, () -> { userService.getUserById(999L); }); }}

3.3 测试私有方法

虽然不推荐直接测试私有方法,但有时确实需要:

import org.junit.jupiter.api.Test;import java.lang.reflect.Method;public class PrivateMethodTest { @Test public void testPrivateMethod() throws Exception { MyService service = new MyService(); Method method = MyService.class.getDeclaredMethod(\"privateMethod\", String.class); method.setAccessible(true); String result = (String) method.invoke(service, \"input\"); assertEquals(\"expected\", result); }}

4. 测试配置

4.1 使用测试配置文件

创建 src/test/resources/application-test.properties

spring.datasource.url=jdbc:h2:mem:testdbspring.datasource.driver-class-name=org.h2.Driverspring.datasource.username=saspring.datasource.password=spring.h2.console.enabled=true

然后在测试类上使用:

@ActiveProfiles(\"test\")

4.2 使用测试切片

Spring Boot 提供了多种测试切片注解

  • @WebMvcTest - 只测试MVC层

  • @DataJpaTest - 只测试JPA组件

  • @JsonTest - 只测试JSON序列化

  • @RestClientTest - 只测试REST客户端

    @WebMvcTest(UserController.class)public class UserControllerSliceTest { @Autowired private MockMvc mockMvc; @MockBean private UserService userService; @Test public void testGetUser() throws Exception { when(userService.getUserById(1L)).thenReturn(new User(1L, \"test@example.com\", \"Test User\")); mockMvc.perform(get(\"/api/users/1\"))  .andExpect(status().isOk())  .andExpect(jsonPath(\"$.name\").value(\"Test User\")); }}

5. 测试最佳实践

  1. 命名规范:测试方法名应清晰表达测试意图,如 shouldReturnUserWhenValidIdProvided()

  2. 单一职责:每个测试方法只测试一个功能点

  3. AAA模式:遵循Arrange-Act-Assert模式组织测试代码

  4. 避免依赖:测试之间不应有依赖关系

  5. 快速反馈:保持测试快速执行,避免I/O操作

  6. 覆盖率:追求合理的测试覆盖率,但不要盲目追求100%

  7. Mock适度:不要过度使用mock,集成测试也很重要


6. 高级主题

6.1 自定义测试注解

import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.ActiveProfiles;import java.lang.annotation.*;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@SpringBootTest@ActiveProfiles(\"test\")public @interface MyIntegrationTest {}

然后可以在测试类上使用 @MyIntegrationTest 替代多个注解。

6.2 测试容器支持

使用Testcontainers进行集成测试:

import org.junit.jupiter.api.Test;import org.testcontainers.containers.PostgreSQLContainer;import org.testcontainers.junit.jupiter.Container;import org.testcontainers.junit.jupiter.Testcontainers;import org.springframework.boot.test.context.SpringBootTest;@Testcontainers@SpringBootTestpublic class UserRepositoryTestContainersTest { @Container public static PostgreSQLContainer postgreSQLContainer = new PostgreSQLContainer(\"postgres:13\") .withDatabaseName(\"testdb\") .withUsername(\"test\") .withPassword(\"test\"); @Test public void testWithRealDatabase() { // 测试代码 }}

6.3 测试Spring Security

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.security.test.context.support.WithMockUser;import org.springframework.test.web.servlet.MockMvc;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;@SpringBootTest@AutoConfigureMockMvcpublic class SecuredControllerTest { @Autowired private MockMvc mockMvc; @Test @WithMockUser(username=\"admin\", roles={\"ADMIN\"}) public void testAdminEndpoint() throws Exception { mockMvc.perform(get(\"/api/admin\"))  .andExpect(status().isOk()); } @Test @WithMockUser(username=\"user\", roles={\"USER\"}) public void testAdminEndpointForbidden() throws Exception { mockMvc.perform(get(\"/api/admin\"))  .andExpect(status().isForbidden()); }}

7. 总结

Spring Boot 提供了全面的测试支持,从单元测试到集成测试,从Mock测试到真实环境测试。合理使用这些工具可以大大提高代码质量和开发效率。

记住测试金字塔原则:多写单元测试,适量集成测试,少量端到端测试。