How to test using StepVerifier a Flux<String> coming from a Controller using WebTestClient in Kotlin?

410 views Asked by At

In Kotlin, I tried to test a simple @RestController using StepVerifier.

  @GetMapping("/helloInt")
  fun helloInt(): Flux<Int> {
    return Flux.range(1, 3).delayElements(Duration.ofMillis(300))
  }

The test is here:

@Test
  fun callingIntEndpoint(){
    var responseBody = webTestClient
      .get()
      .uri("/helloInt")
      .exchange().returnResult<Int>()
    StepVerifier
      .create(responseBody.getResponseBody())
      .expectSubscription()
      .expectNext(1)
      .expectNext(2)
      .expectNext(3)
      .verifyComplete()
  }

And it works just fine. However, when I tried to test a Flux<String>

@GetMapping("/hello")
  fun hello(): Flux<String> {
    return Flux.just("testing", "hello", "Kotlin")
      .delayElements(Duration.ofMillis(300)) //to make sure they are 3 distinct messages
  }

This Unit Test does NOT fail, and it shows clearly what the problem is:

@Test
  fun callingTheEndpoint() {
    webTestClient
      .get()
      .uri("/hello")
      .exchange()
      .returnResult<String>()
      .responseBody
      .test()
      .expectNextMatches { it.equals("testinghelloKotlin") } // but this is NOT what I actually would want to see
      .verifyComplete()
  }

Why is it that the 3 strings are concatenated? When I open the URL in a browser I clearly see the 3 string one by one.

I would like to make this UT work:

@Test
  fun callingTheEndpoint() {
    webTestClient
      .get()
      .uri("/hello")
      .exchange()
      .returnResult<String>()
      .responseBody
      .test()
      .expectNextMatches { it.equals("testing") }
      .expectNextMatches { it.equals("hello") }
      .expectNextMatches { it.equals("Kotlin") }
      .verifyComplete()  }
1

There are 1 answers

0
moldovean On

adding produces = ["text/event-stream"] does the trick

@GetMapping("/hello", produces = ["text/event-stream"])
  fun hello(): Flux<String> {
    return Flux.just("testing", "hello", "Kotlin")
      .delayElements(Duration.ofMillis(300)) //to make sure they are 3 distinct messages
  }