Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest
使用 @WebMvcTest 隔离测试控制器,并使用 @DataJpaTest 测试仓库层
Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest 是 CoddyKit 上的免费 Java Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Java Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Java Academy 课程共包含 4 节课。
什么是测试切片?
测试切片只为特定层加载 Spring 上下文中相关的部分。它比会加载全部内容的 @SpringBootTest 更快,并且可以隔离正在测试的层。
@WebMvcTest:仅控制器层
@WebMvcTest(UserController.class) 只加载 Web 层:控制器、过滤器、安全配置和 Jackson。服务和存储库必须使用 @MockBean 进行模拟。
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired MockMvc mockMvc;
@MockBean UserService userService;
@Test
void get_user_returns_200() throws Exception {
given(userService.findById(1L)).willReturn(new UserDto(1L, "Alice"));
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Alice"));
}
}构建 MockMvc 请求
使用 MockMvcRequestBuilders 构建请求。针对 POST/PUT 测试设置请求头、内容类型和请求体。
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""{"name":"Bob","email":"bob@example.com"}"""))
.andExpect(status().isCreated())
.andExpect(header().exists("Location"));在 @WebMvcTest 中测试验证
无效的请求体会触发 MethodArgumentNotValidException。请断言状态码为 400,并检查错误响应体。
mockMvc.perform(post("/api/users")
.contentType(MediaType.APPLICATION_JSON)
.content("""{"name":"","email":"bad"}"""))
.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.errors.name").exists());@DataJpaTest:仅存储库层
@DataJpaTest 会加载 JPA 存储库、内嵌的 H2 数据库、Hibernate 和 TestEntityManager。其他 Bean(服务、Web 组件)不会被加载。
@DataJpaTest
class UserRepositoryTest {
@Autowired UserRepository repo;
@Autowired TestEntityManager em;
@Test
void find_by_email() {
em.persist(new User("Alice", "alice@example.com"));
em.flush();
Optional<User> found = repo.findByEmail("alice@example.com");
assertTrue(found.isPresent());
}
}TestEntityManager
TestEntityManager 包装了 EntityManager,并提供便捷方法:persist()、flush()、find() 和 persistAndFlush()。
User saved = em.persistAndFlush(new User("Bob", "bob@example.com"));
assertNotNull(saved.getId());
em.clear(); // detach all to force a real DB read
User fromDb = repo.findById(saved.getId()).orElseThrow();
assertEquals("Bob", fromDb.getName());@DataJpaTest 回滚
默认情况下,每个测试都会在一个事务中运行,并在测试结束后回滚。测试之间不会保留数据,从而无需手动清理即可确保测试隔离。
@DataJpaTest // each @Test is rolled back automatically
class OrderRepositoryTest {
@Test @Transactional
void count_orders_is_zero_by_default() {
assertEquals(0, orderRepo.count());
}
}在 @DataJpaTest 中用真实数据库替换 H2
使用 @AutoConfigureTestDatabase(replace = Replace.NONE),让 @DataJpaTest 针对 application.properties 中配置的真实数据库运行,而不是使用 H2。
@DataJpaTest
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class ProductRepositoryTest {
// Uses the configured PostgreSQL, not H2
}@JsonTest:仅测试 JSON 序列化
@JsonTest 会加载 Jackson 配置。使用 JacksonTester 验证对象是否按预期进行序列化和反序列化。
@JsonTest
class UserDtoJsonTest {
@Autowired JacksonTester<UserDto> json;
@Test
void serializes_correctly() throws Exception {
UserDto dto = new UserDto(1L, "Alice", "alice@example.com");
assertThat(json.write(dto)).hasJsonPathStringValue("$.email");
}
}@RestClientTest:REST 客户端层
@RestClientTest 用于测试基于 RestTemplate 或 WebClient 的 HTTP 客户端。它会配置 MockRestServiceServer 来模拟 HTTP 响应。
@RestClientTest(WeatherClient.class)
class WeatherClientTest {
@Autowired WeatherClient client;
@Autowired MockRestServiceServer server;
@Test
void fetches_weather() {
server.expect(requestTo("/api/weather")).andRespond(withSuccess("""{"temp":22}""", APPLICATION_JSON));
Weather w = client.getWeather("Istanbul");
assertEquals(22, w.getTemp());
}
}使用 @Import 组合切片
切片会按照设计排除许多 Bean。使用 @Import(SomeConfig.class) 添加切片所需的特定配置类。
@WebMvcTest(UserController.class)
@Import(SecurityConfig.class) // load security for auth tests
class SecuredControllerTest { ... }快速检查
@DataJpaTest 默认使用哪种数据库?
回顾
@WebMvcTest 使用 MockMvc 测试控制器层,并使用 @MockBean 模拟服务。@DataJpaTest 使用 TestEntityManager 测试存储库,并自动回滚。使用 Replace.NONE 连接真实数据库。使用 @JsonTest 测试序列化,使用 @RestClientTest 测试 HTTP 客户端。
常见问题解答
「Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest」课时是免费的吗?
是的 — 「Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Java Academy 课程的其余内容,请升级到 CoddyKit PRO。 Java Academy 课程共包含 4 节课。
「Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest」这节课中我会学到什么?
使用 @WebMvcTest 隔离测试控制器,并使用 @DataJpaTest 测试仓库层 你通过在浏览器中直接运行的动手代码来练习 Java Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Java Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Java Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Java Academy 课中编写并运行代码吗?
能。每节 Java Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。
此课程中的所有课时
- 使用 @CsvSource 和 @MethodSource 编写参数化测试
- Mockito 进阶:参数捕获器与间谍
- Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest
- Testcontainers:真实数据库集成测试