使用 Spring Boot 3.4 中 MockMvc 的 AssertJ 提高测试可读性-Spring专区论坛-技术-SpringForAll社区

使用 Spring Boot 3.4 中 MockMvc 的 AssertJ 提高测试可读性

d2b5ca33bd20250125113843

Spring Boot 3.4 中我发现非常重要的下一个特性是通过引入一个全新的测试类 MockMvcTester 来支持 AssertJ 进行 MockMvc 测试。在本文中,我们想深入探讨 Spring Boot 3.4 中的这一新特性,看看它如何帮助我们的 MockMvc 测试并提高测试的可读性。

我为这篇文章编写了一个非常基础的 Spring MVC 控制器,带有一个 /hello 端点:

@RestController
@SpringBootApplication
public class DemoMockmvcApplication {

 public static void main(String[] args) {
  SpringApplication.run(DemoMockmvcApplication.class, args);
 }

 @GetMapping("hello")
 public String hello(){
  return "Hello Spring!";
 }

}

这是社区最常请求的功能之一,用于使用 MockMvc 测试 Spring MVC 应用程序。传统上, MockMvc 使用 Hamcrest 来定义断言,这些断言的语法相比 AssertJ 不够易读和简洁。 AssertJ 因其流畅的 API 和简洁的语法在 Java 开发者中非常流行,这导致在为 Spring 项目编写测试时产生了一种二分法。

通过这种方式,Spring 开发者通常选择 AssertJ 来编写测试中的断言,但对于测试 Spring MVC 控制器中的断言,我们必须使用 Hamcrest 匹配器!

@SpringBootTest
@AutoConfigureMockMvc
class DemoMockmvcApplicationTests {

 @Autowired
 private MockMvc mockMvc;

 @Test
 void helloEndpoint_shouldReturnHelloMessage_hamcrest() throws Exception {
  this.mockMvc.perform(get("/hello"))
    .andExpect(status().isOk())
    .andExpect(content().string(containsString("Hello Spring!")));
 }
}

或者使用 AssertJ 断言在 MockMvc 匹配器中:

@SpringBootTest
@AutoConfigureMockMvc
class DemoMockmvcApplicationTests {

 @Autowired
 private MockMvc mockMvc;

 @Test
 void helloEndpoint_shouldReturnHelloMessage_assertj() throws Exception {
  this.mockMvc.perform(get("/hello"))
    .andExpect(status().isOk())
    .andExpect(result -> assertThat(result.getResponse().getContentAsString())
      .isEqualTo("Hello Spring!"));
 }
}

MockMvcTester 是如何工作的?

从 Spring Boot 3.4 开始,为我们提供了一个自动配置的 MockMvcTester ,它允许我们使用 AssertJ 流畅的 API 定义请求和断言。 MockMvcTester 建立在普通的 MockMvc 之上,并允许我们构建请求并返回一个与 AssertJ 兼容的结果,以便可以将其包装在标准的 assertThat() 方法中。

@SpringBootTest
@AutoConfigureMockMvc
class DemoMockmvcApplicationTests {

 @Autowired
 private MockMvcTester mockMvcTester;

 @Test
 void helloEndpoint_shouldReturnHelloMessage_mockMvcTester() {
  mockMvcTester.get().uri("/hello").assertThat() //or - assertThat(mockMvcTester.get().uri("/hello")) 
    .hasStatusOk()
    .bodyText().isEqualTo("Hello Spring!");
 }
}

使用 MockMvcTester 相较于 MockMvc 的优势

MockMvcTester 是围绕 MockMvc 构建的,但它有几个优势:

  • 无需为 AssertJ 断言使用静态导入,因为请求和断言都可以使用流畅的 API 来构建。
  • 未解决的异常会得到一致处理,因此您的测试不需要抛出(或捕获) Exception (我们需要为 MockMvc 处理它)
  • 默认情况下,无论处理是异步还是同步,断言的结果都是完整的。换句话说,不需要以特殊方式处理异步请求。
  • 除了 MockMvcTester 的 AssertJ 断言外,还有几种方法可以在原始的 MockMvc API 中集成 MockMvcTester 与 MockMvc (了解更多方法请点击此处)。

总结

Spring Boot 3.4 中 AssertJ 与 MockMvc 的集成为偏好 AssertJ 而非其他替代方案的 Spring 开发者提供了一种统一编写测试的重要进步。通过 AssertJ 提供的流畅且富有表现力的断言,控制器测试用例的可读性和可维护性将得到提升。

请登录后发表评论

    没有回复内容