MockMvc 接口测试与测试切片
接口写完后要能快速回归。MockMvc 由 spring-test 提供,不真正启动 Servlet 容器,直接向 DispatcherServlet 发起带 HTTP 语义的请求并断言响应,跑得快、适合进 CI,是 Spring Boot Web 层测试最常用的手段。本章示例基于 Spring Boot 3.x(3.5 主线;4.0 已于 2025-11 发布,多数存量工程仍用 3.x)。
起步:@SpringBootTest + @AutoConfigureMockMvc
引入测试依赖(Boot 父 POM 统一管版本,聚合 JUnit5、AssertJ、Mockito、JSONassert):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
全量上下文 + MockMvc 的经典写法:
@SpringBootTest // 加载完整应用上下文
@AutoConfigureMockMvc // 自动装配 MockMvc Bean
class UserControllerTest {
@Autowired
MockMvc mockMvc;
@Test
void getUser_shouldReturn200() throws Exception {
mockMvc.perform(MockMvcRequestBuilders.get("/api/users/1"))
.andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.name").value("张三"));
// 输出:HTTP 200,且响应 JSON 的 name 字段为「张三」
}
}
perform 发起请求,andExpect 逐条断言;jsonPath("$.name") 用 JSONPath 语法取字段,andReturn 可拿到完整响应体再做自定义校验。
POST 与 JSON、CSRF 处理
一旦 classpath 里有 spring-security(见第 29 章),写操作默认要求 CSRF 令牌,测试里要带上:
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("{\"name\":\"李四\",\"email\":\"li@example.com\"}")
.with(SecurityMockMvcRequestPostProcessors.csrf())) // 附加 CSRF 令牌
.andExpect(status().isCreated())
.andExpect(jsonPath("$.id").exists());
测试切片:@WebMvcTest
切片(slice)只加载某一层所需 Bean,上下文小、启动快。@WebMvcTest 只装配 Controller、@ControllerAdvice 与 MVC 基础组件,Service 用测试替身打桩:
@WebMvcTest(UserController.class) // 只加载 Web 层
class UserControllerSliceTest {
@Autowired
MockMvc mockMvc;
@MockitoBean // Boot 3.4+ 推荐写法;旧注解 @MockBean 已弃用
UserService userService;
@Test
void get_shouldCallService() throws Exception {
when(userService.findById(1L)).thenReturn(new UserDto(1L, "张三"));
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("张三"));
}
}
其他常用切片:@DataJpaTest(仅 JPA Repository)、@JsonTest(仅 JSON 序列化)、@RestClientTest(仅 RestClient/WebClient 配置)。切片打桩后断言的只是"自己这层逻辑",全链路正确性交给集成测试(第 25 章)。
切片与全量测试如何选
- 纯 Controller 分支、参数映射、校验提示 → @WebMvcTest,最快;
- 涉及 AOP、事务、跨层联动 → @SpringBootTest 全量;
- 真实网络端口场景 →
@SpringBootTest(webEnvironment = RANDOM_PORT)配合 TestRestTemplate 或 WebTestClient。
小结:单测 Web 层优先 @WebMvcTest + @MockitoBean,全链路用 @SpringBootTest + MockMvc;带 Security 时 POST 请求记得补 CSRF 令牌。