How to test HandlerFunction without RouterFunction in WebFlux using Functional API?

708 views Asked by At

I am writing a simple HTTP server with Spring WebFlux using the Functional API in Kotlin.

As the documentation says, a HandlerFuction handles incoming ServerRequests 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?

0

There are 0 answers