Skip to content

Commit 63958ac

Browse files
committed
Fix concurrent test failure
Since ListenableFuture callbacks are invoked after the future is set, we cannot rely on callbacks having taken place right after a call to future.get(). This change adds a CountdownLatch to detect when the callbacks were invoked. Issue: SPR-12538
1 parent 873b173 commit 63958ac

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

spring-web/src/test/java/org/springframework/web/client/AsyncRestTemplateIntegrationTests.java

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -599,25 +599,20 @@ public void getAndInterceptResponse() throws Exception {
599599
template.setInterceptors(Collections.singletonList(interceptor));
600600
ListenableFuture<ResponseEntity<String>> future = template.getForEntity("/get", String.class);
601601

602-
ResponseEntity<String> response = future.get();
602+
interceptor.latch.await(5, TimeUnit.SECONDS);
603603
assertNotNull(interceptor.response);
604604
assertEquals(HttpStatus.OK, interceptor.response.getStatusCode());
605605
assertNull(interceptor.exception);
606-
assertEquals(helloWorld, response.getBody());
606+
assertEquals(helloWorld, future.get().getBody());
607607
}
608608

609609
@Test
610610
public void getAndInterceptError() throws Exception {
611611
RequestInterceptor interceptor = new RequestInterceptor();
612612
template.setInterceptors(Collections.singletonList(interceptor));
613-
ListenableFuture<ResponseEntity<String>> future = template.getForEntity("/status/notfound", String.class);
613+
template.getForEntity("/status/notfound", String.class);
614614

615-
try {
616-
future.get();
617-
fail("No exception thrown");
618-
} catch (ExecutionException ex) {
619-
// expected
620-
}
615+
interceptor.latch.await(5, TimeUnit.SECONDS);
621616
assertNotNull(interceptor.response);
622617
assertEquals(HttpStatus.NOT_FOUND, interceptor.response.getStatusCode());
623618
assertNull(interceptor.exception);
@@ -632,6 +627,8 @@ private void waitTillDone(ListenableFuture<?> future) {
632627

633628
private static class RequestInterceptor implements AsyncClientHttpRequestInterceptor {
634629

630+
private final CountDownLatch latch = new CountDownLatch(1);
631+
635632
private volatile ClientHttpResponse response;
636633

637634
private volatile Throwable exception;
@@ -654,7 +651,15 @@ public URI getURI() {
654651
};
655652

656653
ListenableFuture<ClientHttpResponse> future = execution.executeAsync(request, body);
657-
future.addCallback(resp -> response = resp, ex -> exception = ex);
654+
future.addCallback(
655+
resp -> {
656+
response = resp;
657+
this.latch.countDown();
658+
},
659+
ex -> {
660+
exception = ex;
661+
this.latch.countDown();
662+
});
658663
return future;
659664
}
660665
}

0 commit comments

Comments
 (0)