diff --git a/core-java-modules/core-java-concurrency-simple/pom.xml b/core-java-modules/core-java-concurrency-simple/pom.xml index a16df4fc97..720ab5a0ed 100644 --- a/core-java-modules/core-java-concurrency-simple/pom.xml +++ b/core-java-modules/core-java-concurrency-simple/pom.xml @@ -12,6 +12,15 @@ 0.0.1-SNAPSHOT + + + org.wiremock + wiremock + 3.1.0 + test + + + core-java-concurrency-simple diff --git a/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/completablefuture/CompletableFutureTimeoutUnitTest.java b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/completablefuture/CompletableFutureTimeoutUnitTest.java new file mode 100644 index 0000000000..f54e5f4af5 --- /dev/null +++ b/core-java-modules/core-java-concurrency-simple/src/test/java/com/baeldung/concurrent/completablefuture/CompletableFutureTimeoutUnitTest.java @@ -0,0 +1,83 @@ +package com.baeldung.concurrent.completablefuture; + +import com.github.tomakehurst.wiremock.WireMockServer; +import com.github.tomakehurst.wiremock.client.WireMock; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.*; + +import static com.github.tomakehurst.wiremock.client.WireMock.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +public class CompletableFutureTimeoutUnitTest { + private static WireMockServer wireMockServer; + private static ScheduledExecutorService executorService; + private static final int DEFAULT_TIMEOUT = 500; //0.5 seconds + private static final int TIMEOUT_STATUS_CODE = 408; //0.5 seconds + + @BeforeAll + public static void setUp() { + wireMockServer = new WireMockServer(8080); + wireMockServer.start(); + WireMock.configureFor("localhost", 8080); + + stubFor(get(urlEqualTo("/api/dummy")) + .willReturn(aResponse() + .withFixedDelay(5000) // must be > DEFAULT_TIMEOUT for a timeout to occur. + .withStatus(408))); + + executorService = Executors.newScheduledThreadPool(1); + } + + + @AfterAll + public static void tearDown() { + executorService.shutdown(); + wireMockServer.stop(); + } + + private CompletableFuture createDummyRequest() { + return CompletableFuture.supplyAsync(() -> { + try { + URL url = new URL("http://localhost:8080/api/dummy"); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + try { + return connection.getResponseCode(); + } finally { + connection.disconnect(); + } + } catch (IOException e) { + return TIMEOUT_STATUS_CODE; + } + }); + } + + @Test + public void whenorTimeout_thenGetThrow() { + CompletableFuture completableFuture = createDummyRequest() + .orTimeout(DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + assertThrows(ExecutionException.class, completableFuture::get); + } + + @Test + public void whencompleteOnTimeout_thenReturnValue() throws ExecutionException, InterruptedException { + CompletableFuture completableFuture = createDummyRequest() + .completeOnTimeout(TIMEOUT_STATUS_CODE, DEFAULT_TIMEOUT, + TimeUnit.MILLISECONDS); + assertEquals(TIMEOUT_STATUS_CODE, completableFuture.get()); + } + + @Test + public void whencompleteExceptionally_thenGetThrow() { + CompletableFuture completableFuture = createDummyRequest(); + executorService.schedule(() -> completableFuture + .completeExceptionally(new TimeoutException("Timeout occurred")), DEFAULT_TIMEOUT, TimeUnit.MILLISECONDS); + assertThrows(ExecutionException.class, completableFuture::get); + } + +}