Spring Webflux 和 Spring Web 是两个完全不同的网络堆栈。 Spring Webflux却继续支持基于注解的编程模型
使用这两个堆栈定义的端点可能看起来很相似,但测试此类端点的方式却大不相同,编写此类端点的用户必须知道哪个堆栈处于活动状态并相应地制定测试。
考虑一个基于示例注释的端点:
import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.RequestBody import org.springframework.web.bind.annotation.RequestMapping import org.springframework.web.bind.annotation.RestController data class Greeting(val message: String) @RestController @RequestMapping("/web") class GreetingController { @PostMapping("/greet") fun handleGreeting(@RequestBody greeting: Greeting): Greeting { return Greeting("Thanks: ${greeting.message}") } }
如果使用 Spring Boot 2 启动器 创建此应用程序,并以 Spring Web 作为启动器,则使用 Gradle 构建文件按以下方式指定:
compile('org.springframework.boot:spring-boot-starter-web')
那么对这样一个端点的测试将使用 Mock web 运行时,称为 Mock MVC:
import org.junit.Test import org.junit.runner.RunWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest import org.springframework.test.context.junit4.SpringRunner import org.springframework.test.web.servlet.MockMvc import org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content @RunWith(SpringRunner::class) @WebMvcTest(GreetingController::class) class GreetingControllerMockMvcTest { @Autowired lateinit var mockMvc: MockMvc @Test fun testHandleGreetings() { mockMvc .perform( post("/web/greet") .content(""" |{ |"message": "Hello Web" |} """.trimMargin()) ).andExpect(content().json(""" |{ |"message": "Thanks: Hello Web" |} """.trimMargin())) } }
另一方面,如果引入了 Spring-Webflux 启动器,则使用以下 Gradle 依赖项:
compile('org.springframework.boot:spring-boot-starter-webflux')
那么这个端点的测试将使用优秀的 WebTestClient 类,沿着这些线:
import org.junit.Test import org.junit.runner.RunWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest import org.springframework.http.HttpHeaders import org.springframework.test.context.junit4.SpringRunner import org.springframework.test.web.reactive.server.WebTestClient import org.springframework.web.reactive.function.BodyInserters @RunWith(SpringRunner::class) @WebFluxTest(GreetingController::class) class GreetingControllerTest { @Autowired lateinit var webTestClient: WebTestClient @Test fun testHandleGreetings() { webTestClient.post() .uri("/web/greet") .header(HttpHeaders.CONTENT_TYPE, "application/json") .body(BodyInserters .fromObject(""" |{ | "message": "Hello Web" |} """.trimMargin())) .exchange() .expectStatus().isOk .expectBody() .json(""" |{ | "message": "Thanks: Hello Web" |} """.trimMargin()) } }
很容易假设,由于使用 Spring Web 和 Spring Webflux 堆栈的编程模型看起来非常相似,因此使用 Spring Web 进行的此类遗留测试的测试将继续到 Spring Webflux,但事实并非如此,作为开发人员,我们有注意发挥作用的底层堆栈并相应地制定测试。我希望这篇文章能阐明应该如何设计这样的测试。
标签2: Java教程地址:https://www.cundage.com/article/jcg-annotated-controllers-spring-web-webflux-testing.html