0Pricing
Java Academy · 课时

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 反馈 — 无需本地设置。

此课程中的所有课时

  1. 使用 @CsvSource 和 @MethodSource 编写参数化测试
  2. Mockito 进阶:参数捕获器与间谍
  3. Spring Boot 测试切片:@WebMvcTest 与 @DataJpaTest
  4. Testcontainers:真实数据库集成测试
← 返回 Java Academy