Prompts-MCP 686 skills · ai / design / design-pattern / framework / fundamentals / habit / lang / tech-selection /mcp/sse
framework framework/testing/spring-boot-test.md medium

testing-spring-boot-test

Spring Boot 测试分层选型 — @SpringBootTest 全容器集成 vs @WebMvcTest 切 controller 层 vs 纯单测不起 Spring。Use when 纠结要不要起 Spring 容器 / 选哪个测试注解时。

集成测试测试切片@springboottest@webmvctestmockmvc@mockbean
paths
  • *.java

Spring Boot · 测试注解选型

本条只管「起不起 Spring、起多大、用哪个注解」。Mockito 打桩语法见 mockito-stubbing.md;分层比例见 test-pyramid.md

选型表(从快到慢,能小别大)

场景 用什么 起多少 Spring
测 service/util 纯逻辑 纯单测(JUnit5 + Mockito,不加 Spring 注解) 不起容器,最快
测 controller 的路由/参数绑定/返回 JSON @WebMvcTest(Xxx.class) + MockMvc 只切 Web 层,service 用 @MockBean
测 dao/repository 真实读写 @DataJpaTest / @MybatisTest 只切持久层 + 内存库
测多层串起来的完整链路 @SpringBootTest 起全量容器,最慢,量要少

正例

// ① controller 层切片:只起 Web,service 被 mock
@WebMvcTest(UserController.class)
class UserControllerTest {

    @Autowired MockMvc mockMvc;
    @MockBean UserService userService;   // 切片内 mock 协作 Bean

    @Test
    void get_shouldReturn200() throws Exception {
        when(userService.getById(1L)).thenReturn(new UserVO("Tom"));
        mockMvc.perform(get("/users/1"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.data.name").value("Tom"));
    }
}

// ② 完整集成:起整个上下文,少量关键链路才用
@SpringBootTest
@AutoConfigureMockMvc
class OrderFlowIT {
    @Autowired MockMvc mockMvc;
    // ... 跑下单全链路
}

切片里替换 Bean 用 @MockBean(进 Spring 容器),纯单测里用 @Mock(不进容器)—— 别混用。

反例

// ❌ 只想测 controller 的 JSON 格式,却起全量 @SpringBootTest
@SpringBootTest                 // 连 DB/MQ/缓存全拉起,几秒一个用例,CI 拖垮
class UserControllerTest {
    // 该用 @WebMvcTest
}

❌ 测纯工具类还加 @SpringBootTest —— 起容器纯属浪费,直接 new 对象单测。

自检

  • [ ] 纯逻辑用纯单测,没无谓地起 Spring 容器?
  • [ ] 测 controller 用 @WebMvcTest + MockMvc,而非全量集成?
  • [ ] 切片内替换 Bean 用 @MockBean,纯单测用 @Mock,没混?
  • [ ] @SpringBootTest 只留给少量必须的端到端链路?

相关