欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > Spring Boot 单元测试使用教程(仅供参考)

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

2025/5/8 5:25:01 来源:https://blog.csdn.net/weixin_52578852/article/details/147346568  浏览:    关键词:Spring Boot 单元测试使用教程(仅供参考)

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


1. 准备工作

1.1 添加测试依赖

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

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency><!-- 如果需要MockMvc -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><scope>test</scope>
</dependency><!-- 如果需要AssertJ -->
<dependency><groupId>org.assertj</groupId><artifactId>assertj-core</artifactId><version>3.24.2</version><scope>test</scope>
</dependency>

1.2 测试类基本结构

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class MyApplicationTests {@Testpublic 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 {@Mockprivate UserRepository userRepository;@InjectMocksprivate UserService userService;@Testpublic 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
@AutoConfigureMockMvc
public class UserControllerTest {@Autowiredprivate MockMvc mockMvc;@Testpublic 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
@AutoConfigureWebTestClient
public class UserControllerWebTestClientTest {@Autowiredprivate WebTestClient webTestClient;@Testpublic 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.*;@DataJpaTest
public class UserRepositoryTest {@Autowiredprivate TestEntityManager entityManager;@Autowiredprivate UserRepository userRepository;@Testpublic 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")
@Transactional
public class UserServiceIntegrationTest {@Autowiredprivate UserService userService;@Autowiredprivate UserRepository userRepository;@Testpublic 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 {@Testpublic 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 {@Testpublic 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:testdb
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.username=sa
spring.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 {@Autowiredprivate MockMvc mockMvc;@MockBeanprivate UserService userService;@Testpublic 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
@SpringBootTest
public class UserRepositoryTestContainersTest {@Containerpublic static PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>("postgres:13").withDatabaseName("testdb").withUsername("test").withPassword("test");@Testpublic 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
@AutoConfigureMockMvc
public class SecuredControllerTest {@Autowiredprivate 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测试到真实环境测试。合理使用这些工具可以大大提高代码质量和开发效率。

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

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词