I am writing a simple HTTP server with Spring WebFlux using the Functional API in Kotlin.
As the documentation says, a HandlerFuction
handles incoming ServerRequest
s by returning a Mono<ServerResponse>
on invocation.
Let's assume, we have the following function which responses with either OK or BAD_REQUEST depending on whether the name path variable is presented:
val helloHandler = HandlerFunction { req ->
try {
val name = req.pathVariable("name")
ok().bodyValue("Hello $name!")
} catch (_: IllegalArgumentException) {
badRequest().build()
}
}
The Testing section of Spring Reference Guide implies that this function should be tested with the conjunction of its RouterFunction
using WebTestClient
. Such a test would look like this:
val helloHandlerRouter = RouterFunctions.route()
.GET("/hello/{name}", helloHandler)
.build()
val client = WebTestClient
.bindToRouterFunction(helloHandlerRouter)
.build()
client.get().uri("/hello/Panda").exchange()
.expectStatus().isOk
.expectBody<String>().isEqualTo("Hello Panda!")
While this test seems satisfying, it highly depends on the underlying routing mechanism. For example, it would return NOT_FOUND instead of BAD_REQUEST on missing name path variable ignoring the actual handler logic. The router intercepts by simply not forwarding the request to the handler, ergo, the following test is testing the router not the handler:
client.get().uri("/hello").exchange()
.expectStatus().isBadRequest // FAILS: NOT_FOUND != BAD_REQUEST
.expectBody().isEmpty
How to test the HandlerFunction
without its router?
I would like to test the HandlerFunction
in isolation, somehow like this:
val request = MockServerRequest.builder()
.pathVariable("name", "Panda")
.build()
val response: Mono<ServerResponse> = helloHandler.handle(request).block()
// ??? verify ???
But I did not find a sufficient way to watch inside to the response and verify its values.
Could you please advise on how to test HandleFunctions
separately from their RouterFunctions
?