Как протестировать функцию HandlerFunction без функции RouterFunction в WebFlux с использованием функционального API?

#spring #spring-webflux #project-reactor #spring-reactive

#spring #spring-webflux #проект-реактор #spring-реактивный

Вопрос:

Я пишу простой HTTP-сервер с Spring WebFlux, используя функциональный API в Kotlin.

Как говорится в документации, a HandlerFuction обрабатывает входящие ServerRequest s, возвращая a Mono<ServerResponse> при вызове.

Предположим, у нас есть следующая функция, которая отвечает либо OK, либо BAD_REQUEST в зависимости от того, представлена ли переменная name path:

 val helloHandler = HandlerFunction { req ->
    try {
        val name = req.pathVariable("name")
        ok().bodyValue("Hello $name!")
    } catch (_: IllegalArgumentException) {
        badRequest().build()
    }
}

  

Раздел тестирования справочного руководства Spring подразумевает, что эту функцию следует тестировать в сочетании с ее RouterFunction использованием WebTestClient . Такой тест будет выглядеть так:

 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!")
  

Хотя этот тест кажется удовлетворительным, он сильно зависит от базового механизма маршрутизации. Например, он вернет NOT_FOUND вместо BAD_REQUEST для отсутствующей переменной пути имени, игнорируя фактическую логику обработчика. Маршрутизатор перехватывает, просто не пересылая запрос обработчику, следовательно, следующий тест проверяет маршрутизатор, а не обработчик:

 client.get().uri("/hello").exchange()
    .expectStatus().isBadRequest // FAILS: NOT_FOUND != BAD_REQUEST 
    .expectBody().isEmpty
  

Как протестировать HandlerFunction без маршрутизатора?

Я хотел бы протестировать HandlerFunction изолированно, как-то так:

 val request = MockServerRequest.builder()
    .pathVariable("name", "Panda")
    .build()
val response: Mono<ServerResponse> = helloHandler.handle(request).block()

// ??? verify ???
  

Но я не нашел достаточного способа посмотреть внутри ответа и проверить его значения.

Не могли бы вы посоветовать, как тестировать HandleFunctions отдельно от их RouterFunctions ?

Комментарии:

1. покажите нам ту часть, где функция обработчика сопоставляется с ее URL.

2. Спасибо, @ThomasAndolf. Теперь найдите RouterFunction реализацию в описании.

3. проблема в том, что вы предполагаете, что /hello и /hello/{name} является URL-адресом, которым он не является. Это 2 отдельные конечные точки.

4. Или, еще точнее RouterFunction , вернет пустое Mono<ServerResponse> значение, поскольку RequestPredicate в GET / hello не найдено совпадений. Следовательно, маршрутизатор отвечает 404 (см. Здесь ). Но это поведение все еще находится в маршрутизаторе, в то время как я намерен протестировать HandlerFunction .

5. если вы хотите протестировать свою функцию-обработчик, вам следует использовать step verifier, а затем имитировать ваш запрос, а не использовать макет webclient