Spring Webflux and Spring Web are two entirely different web stacks. Spring Webflux, however, continues to support an annotation-based programming model
An endpoint defined using these two stacks may look similar but the way to test such an endpoint is fairly different and a user writing such an endpoint has to be aware of which stack is active and formulate the test accordingly.
then the test of such an endpoint would be using a Mock web runtime, referred to as Mock MVC:
then the test of this endpoint would be using the excellent WebTestClient class, along these lines:
An endpoint defined using these two stacks may look similar but the way to test such an endpoint is fairly different and a user writing such an endpoint has to be aware of which stack is active and formulate the test accordingly.
Sample Endpoint
Consider a sample annotation based endpoint:
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}")
}
}
Testing with Spring Web
If Spring Boot 2 starters were used to create this application with Spring Web as the starter, specified using a Gradle build file the following way:compile('org.springframework.boot:spring-boot-starter-web')
then the test of such an endpoint would be using a Mock web runtime, referred to as 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()))
}
}
Testing with Spring Web-Flux
If on the other hand Spring-Webflux starters were pulled in, say with the following Gradle dependency:compile('org.springframework.boot:spring-boot-starter-webflux')
then the test of this endpoint would be using the excellent WebTestClient class, along these lines:
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())
}
}