聊一聊Spring框架接口测试常见场景有哪些?

发布于:2025-07-13 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

一、基础 REST API 测试场景

1. GET 请求验证

2. POST 请求验证​​​​​​​

二、复杂业务场景

1. 参数校验失败测试​​​​​​​

2. 分页查询测试​​​​​​​

三、安全相关场景

1. 认证失败测试​​​​​​​

2. 角色权限验证​​​​​​​

四、数据持久化场景

1. 数据库集成测试​​​​​​​

2. 事务回滚测试​​​​​​​

五、外部依赖处理场景

1. HTTP 服务模拟 (MockWebServer)​​​​​​​

2. 数据库容器化测试 (Testcontainers)​​​​​​​

六、异步接口测试​​​​​​​

七、文件上传/下载测试

1. 文件上传​​​​​​​

2. 文件下载​​​​​​​

八、性能与压力测试

九、建议

测试分层策略

测试数据管理

环境隔离


Spring框架进行接口测试包含对接口的功能测试,数据访问,性能测试等。功能测试,验证接口是否按照需求工作,比如正确的输入输出、业务逻辑处理。还有异常处理测试,比如当传入无效参数时,接口是否能正确返回错误信息。参数验证也是关键,比如使用@Validated注解时的验证逻辑是否生效。

数据访问测试,比如使用Spring Data JPA或MyBatis时,数据库操作是否正确,事务管理是否有效。权限控制测试,比如Spring Security的权限验证,不同角色用户访问接口的结果是否符合预期。

性能测试,比如接口的响应时间、并发处理能力。安全测试,比如SQL注入、XSS攻击的防护。依赖服务测试,比如模拟外部服务(如RESTful API、数据库)的行为,确保接口在依赖服务不可用时的处理。

Spring特有的测试工具,比如@WebMvcTest用于控制器层的测试,@DataJpaTest用于数据层的测试,以及如何利用MockBean来模拟Bean的行为。此外,异常处理测试中,可以提到使用@ControllerAdvice和@ExceptionHandler来统一处理异常,并测试这些处理是否正确。

一、基础 REST API 测试场景

1. GET 请求验证​​​​​​​

@SpringBootTest@AutoConfigureMockMvcclass UserControllerTest {    @Autowired MockMvc mockMvc;    @Test    void getUsers_shouldReturn200() throws Exception {        mockMvc.perform(get("/api/users"))               .andExpect(status().isOk())               .andExpect(jsonPath("$[0].name").value("Alice"));    }    @Test    void getUserById_shouldReturn404() throws Exception {        mockMvc.perform(get("/api/users/999")) // 不存在的ID               .andExpect(status().isNotFound());    }}

2. POST 请求验证​​​​​​​

@Testvoid createUser_shouldReturn201() throws Exception {    String jsonBody = """        { "name": "Bob", "email": "bob@example.com" }        """;    mockMvc.perform(post("/api/users")            .contentType(MediaType.APPLICATION_JSON)            .content(jsonBody))           .andExpect(status().isCreated())           .andExpect(header().exists("Location"));}

二、复杂业务场景

1. 参数校验失败测试​​​​​​​

@Testvoid createUser_invalidEmail_shouldReturn400() throws Exception {    String invalidJson = "{ \"name\": \"\", \"email\": \"invalid\" }";    mockMvc.perform(post("/api/users")            .content(invalidJson)            .contentType(MediaType.APPLICATION_JSON))           .andExpect(status().isBadRequest())           .andExpect(jsonPath("$.errors").isArray());}

2. 分页查询测试​​​​​​​

@Testvoid getUsers_withPagination() throws Exception {    mockMvc.perform(get("/api/users")            .param("page", "2")            .param("size", "10"))           .andExpect(status().isOk())           .andExpect(jsonPath("$.content.length()").value(10));}

三、安全相关场景

1. 认证失败测试​​​​​​​

@Testvoid getSecretData_withoutAuth_shouldReturn401() throws Exception {    mockMvc.perform(get("/api/secret"))           .andExpect(status().isUnauthorized());}

2. 角色权限验证​​​​​​​

@Test@WithMockUser(roles = "USER")void deleteUser_asUser_shouldReturn403() throws Exception {    mockMvc.perform(delete("/api/users/1"))           .andExpect(status().isForbidden());}@Test@WithMockUser(roles = "ADMIN")void deleteUser_asAdmin_shouldSucceed() throws Exception {    mockMvc.perform(delete("/api/users/1"))           .andExpect(status().isNoContent());}

四、数据持久化场景

1. 数据库集成测试​​​​​​​

@DataJpaTest@AutoConfigureTestDatabase(replace = Replace.NONE)class UserRepositoryTest {    @Autowired TestEntityManager entityManager;    @Autowired UserRepository repository;    @Test    void findByEmail_shouldReturnUser() {        User user = new User("test@example.com");        entityManager.persist(user);        Optional<User> found = repository.findByEmail("test@example.com");        assertThat(found).isPresent();    }}

2. 事务回滚测试​​​​​​​

@SpringBootTest@Transactionalclass UserServiceIntegrationTest {    @Autowired UserService service;    @Test    void createUser_shouldRollbackOnException() {        assertThrows(DataIntegrityViolationException.class, () -> {            service.createUser(new User(null)); // 无效数据        });        // 验证数据未持久化        assertThat(service.countUsers()).isEqualTo(0);    }}

五、外部依赖处理场景

1. HTTP 服务模拟 (MockWebServer)​​​​​​​

@SpringBootTest@AutoConfigureMockMvc@Testcontainersclass PaymentControllerTest {    @Container    static MockWebServer externalService = new MockWebServer();    @DynamicPropertySource    static void setProperties(DynamicPropertyRegistry registry) {        registry.add("payment.service.url",             () -> externalService.url("/").toString());    }    @Test    void processPayment() throws Exception {        // 设置模拟响应        externalService.enqueue(new MockResponse()                .setBody("{\"status\":\"SUCCESS\"}")                .addHeader("Content-Type", "application/json"));        mockMvc.perform(post("/api/payments"))               .andExpect(status().isOk());    }}

2. 数据库容器化测试 (Testcontainers)​​​​​​​

@Testcontainers@DataJpaTest@AutoConfigureTestDatabase(replace = Replace.NONE)class UserRepositoryContainerTest {    @Container    static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15");    @DynamicPropertySource    static void configureProperties(DynamicPropertyRegistry registry) {        registry.add("spring.datasource.url", postgres::getJdbcUrl);        registry.add("spring.datasource.username", postgres::getUsername);        registry.add("spring.datasource.password", postgres::getPassword);    }    @Test    void testDatabaseConnection() {        // 测试逻辑    }}

六、异步接口测试​​​​​​​

@Testvoid asyncOperation_shouldComplete() throws Exception {    MvcResult result = mockMvc.perform(get("/api/async"))            .andExpect(request().asyncStarted())            .andReturn();    mockMvc.perform(asyncDispatch(result))            .andExpect(status().isOk())            .andExpect(content().string("Operation completed"));}

七、文件上传/下载测试

1. 文件上传​​​​​​​

@Testvoid uploadFile_shouldSucceed() throws Exception {    MockMultipartFile file = new MockMultipartFile(        "file", "test.txt", "text/plain", "Hello World".getBytes()    );    mockMvc.perform(multipart("/api/files").file(file))            .andExpect(status().isOk());}

2. 文件下载​​​​​​​

@Testvoid downloadFile_shouldReturnContent() throws Exception {    mockMvc.perform(get("/api/files/1"))            .andExpect(status().isOk())            .andExpect(header().string(                HttpHeaders.CONTENT_DISPOSITION,                 "attachment; filename=\"report.pdf\""            ))            .andExpect(content().contentType(MediaType.APPLICATION_PDF));}

八、性能与压力测试

结合 Spring Boot Actuator 和 JMeter:​​​​​​​

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)class UserControllerLoadTest {    @LocalServerPort int port;    @Test    void stressTest() {        HttpRequest request = HttpRequest.newBuilder()                .uri(URI.create("http://localhost:" + port + "/api/users"))                .GET()                .build();        // 使用JMeter或自定义压力测试工具        loadTest(request, 1000); // 模拟1000并发请求    }}

九、建议

测试分层策略

Controller 层:使用 MockMvc 模拟 HTTP 请求

Service 层:使用 @MockBean 模拟依赖

Repository 层:使用 @DataJpaTest + 嵌入式数据库

测试数据管理

使用 @Sql 注解初始化数据

测试后自动清理数据(@Transactional)

环境隔离

生产环境配置:application-prod.properties

测试环境配置:application-test.properties

使用 @ActiveProfiles("test") 激活配置


网站公告

今日签到

点亮在社区的每一天
去签到