40

I wrote a test for Handler (Spring Webflux)

@Test
public void checkServicesHandlerTest() {
    Request request = new Request();
    request.setMsisdn("ffdfdfd");
    this.testClient.post().uri("/check")
                   .body(Mono.just(request), Request.class)
                   .exchange().expectStatus().isOk();
}

But in result I have an error.

Timeout on blocking read for 5000 MILLISECONDS

The handler is simple:

 public Mono<ServerResponse> check(ServerRequest request) {
       
     Request request = request.bodyToMono(Request.class).block();

Where is the problem? If i send a direct request to server all is ok.

zb226
  • 9,586
  • 6
  • 49
  • 79
Mikhail
  • 2,690
  • 4
  • 28
  • 43
  • 1
    Is that your whole handler implementation? Using `block()` inside a handler is strongly discouraged and this might be the underlying issue. – Brian Clozel Nov 14 '17 at 16:05
  • thanks. wrote without block and it works ok. also can you advise a good course on reator3 Or weblux? – Mikhail Nov 16 '17 at 07:19
  • http://projectreactor.io/learn and https://bclozel.github.io/webflux-workshop/ could be useful – Brian Clozel Nov 16 '17 at 08:01
  • Could you answer your own question then? This might help other SO users. – Brian Clozel Nov 16 '17 at 08:03
  • @BrianClozel I am seeing the same issue. I have a Integration test (using Junit5 and it's Spring boot 2.0.0.RC1) that get's all the users from calling a Webservice that internally gets it from table and that table can have a max of 50-60 users. I see that the test used to pass when the users were 15-20 of them. It's failing now. Please advice. – ROCKY Feb 07 '18 at 03:42
  • Just to add: The "Timeout on blocking read" error can also appear if you're debugging during a testrun, since this can take more time... – Asriel Jul 25 '22 at 07:04

5 Answers5

65

I was seeing similar issue and Exception when running Integration tests some of them aggregates responses from multiple other services which has database access and stuff. So we were seeing this issue intermittently when running Integration tests. We are using Spring Boot 2.0.0.RC1 and Junit 5 with Gradle. I did this to resolve the issue. The key is mutating the webclient with a response timeout of 30 seconds the worst case.

@Autowired
private WebTestClient webTestClient;

@BeforeEach
public void setUp() {
    webTestClient = webTestClient.mutate()
                                 .responseTimeout(Duration.ofMillis(30000))
                                 .build();
}
zb226
  • 9,586
  • 6
  • 49
  • 79
ROCKY
  • 1,763
  • 1
  • 21
  • 25
  • 7
    I always get timeout irrespective of the timeout I set. But my rest api (similar to the one above) works fine if I start the application and test the endpoint directly – DBS Jan 25 '19 at 16:49
  • 2
    Hi, I'm also facing the same issue. still throwing error even if i set timeout. any other idea how to tackle it? – Sam Jul 24 '20 at 04:53
  • I have to say: #me too – du-it Sep 30 '21 at 16:27
57

You can override the timeout by using the annotation @AutoConfigureWebTestClient(timeout = "36000").

for example :

@AutoConfigureWebTestClient(timeout = "36000")
@SpringBootTest
class MyTestClass {
}
  • This didn't have any effect on my Spring Boot WebTestClient's timeout... – zb226 Feb 18 '22 at 11:06
  • 3
    I suggest using the ISO-8601 duration format. Example for 36 seconds: `@AutoConfigureWebTestClient(timeout = "PT36S")` – RoBeaToZ Mar 12 '22 at 11:42
  • This helped ! I increased timeout and now i could see the actual exception instead of the timeout message! – user1354825 Dec 09 '22 at 11:58
  • Is there any environment variable dedicated to achieve the same behavior as using the annotation @AutoConfigureWebTestClient? Having that would make debugging easier as just modifying code and passing run/debug ocnfiguration would suffice. – Ankit Gaurav Aug 08 '23 at 14:03
1

With the WebTestClient you can use @AutoConfigureWebTestClient(timeout = "36000"), the timeout value being a value of your choice. Especially, consider the response time of your third-party service.

0

In case of Kotlin test it could be following example:

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class RouterTests {
    lateinit var client: WebTestClient

    private val dealService: DealService = QshDealService()
    private val dealStream: StreamHandler<MarketData> = DealStream(dealService)
    private lateinit var fileService: FileService

    @BeforeAll
    fun init() {
        val streamHandlers: Map<String, StreamHandler<MarketData>> = mapOf("dealStream" to dealStream)
        fileService = CommonFilesService(streamHandlers)
        val filesHandler = QshFilesHandler(fileService)
        this.client = WebTestClient
            .bindToRouterFunction(QshRouter(filesHandler).route())
            .configureClient()
            .responseTimeout(Duration.ofMillis(30000))
            .build()
    }

    @Test
    fun whenRequestToRoute_thenStatusShouldBeOk() {
        ...
    }

}
Dada
  • 6,313
  • 7
  • 24
  • 43
0

Check you pom file, if BlockHound dependency is present remove it.

<dependency>
  <groupId>io.projectreactor.tools</groupId>
  <artifactId>blockhound</artifactId>
  <version>$LATEST_RELEASE</version>
</dependency>
p_sha
  • 1
  • 3