|
import static org.assertj.core.api.Assertions.assertThat; |
|
import static org.assertj.core.api.Assertions.assertThatThrownBy; |
|
|
|
import java.util.concurrent.CompletableFuture; |
|
import java.util.concurrent.CountDownLatch; |
|
import java.util.concurrent.ThreadLocalRandom; |
|
import java.util.concurrent.TimeUnit; |
|
|
|
import org.junit.Test; |
|
|
|
public class ErrorsTest { |
|
|
|
@Test |
|
public void wrappingWhenCompleteShouldPropagateExceptions() throws Exception { |
|
String randomExceptionMessage = "Failed: " + ThreadLocalRandom.current().nextInt(500); |
|
|
|
// Given |
|
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>(); |
|
|
|
// When (a future completes with an exception) |
|
completableFuture.completeExceptionally(new IllegalArgumentException(randomExceptionMessage)); |
|
|
|
// Then (the error of the original exception is propagated to the wrapped future) |
|
CompletableFuture<Boolean> wrappedFuture = Errors.<Boolean, Boolean>whenComplete(completableFuture).wrap( |
|
(result, error) -> false); |
|
|
|
assertThatThrownBy(() -> wrappedFuture.get(5, TimeUnit.SECONDS)) |
|
.hasCauseExactlyInstanceOf(IllegalArgumentException.class) |
|
.hasMessageContaining(randomExceptionMessage); |
|
} |
|
|
|
@Test |
|
public void wrappingWhenCompleteShouldNotPropagateExceptionsWhenPropagateIsFalse() throws Exception { |
|
String randomExceptionMessage = "Failed: " + ThreadLocalRandom.current().nextInt(500); |
|
|
|
// Given |
|
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>(); |
|
|
|
// When (a future completes with an exception) |
|
completableFuture.completeExceptionally(new IllegalArgumentException(randomExceptionMessage)); |
|
|
|
// Then (the error of the original exception is propagated to the wrapped future) |
|
CompletableFuture<Boolean> wrappedFuture = Errors.<Boolean, Boolean>whenComplete(completableFuture).wrap( |
|
false, // explicitly tell the wrapper not to propagate the original exception |
|
(result, error) -> false); |
|
|
|
assertThat(wrappedFuture.get(5, TimeUnit.SECONDS)).isEqualTo(false); |
|
} |
|
|
|
@Test |
|
public void wrappingWhenCompleteShouldAllowForInspectingError() throws Exception { |
|
String randomExceptionMessage = "Failed: " + ThreadLocalRandom.current().nextInt(500); |
|
|
|
// Given |
|
CountDownLatch latch = new CountDownLatch(1); |
|
CompletableFuture<Boolean> completableFuture = new CompletableFuture<>(); |
|
|
|
// When (a future completes with an exception) |
|
completableFuture.completeExceptionally(new IllegalArgumentException(randomExceptionMessage)); |
|
|
|
// Then (the error of the original exception is propagated to the wrapped future) |
|
CompletableFuture<Boolean> wrappedFuture = Errors.<Boolean, Boolean>whenComplete(completableFuture).wrap( |
|
(result, error) -> { |
|
assertThat(error).isNotNull() |
|
.hasMessageContaining(randomExceptionMessage) |
|
.isExactlyInstanceOf(IllegalArgumentException.class); |
|
assertThat(result).isNull(); |
|
latch.countDown(); |
|
return false; |
|
}); |
|
|
|
latch.await(5, TimeUnit.SECONDS); |
|
} |
|
|
|
|
|
@Test |
|
public void wrappingWhenCompleteShouldProvideResult() throws Exception { |
|
String randomMessage = "Success: " + ThreadLocalRandom.current().nextInt(500); |
|
|
|
// Given |
|
CountDownLatch latch = new CountDownLatch(1); |
|
CompletableFuture<String> completableFuture = new CompletableFuture<>(); |
|
|
|
// When (a future completes with a given result) |
|
completableFuture.complete(randomMessage); |
|
|
|
// Then (the result is accessible to the wrapped future) |
|
CompletableFuture<Boolean> wrappedFuture = Errors.<String, Boolean>whenComplete(completableFuture).wrap( |
|
(result, error) -> { |
|
assertThat(result).isEqualTo(randomMessage); |
|
assertThat(error).isNull(); |
|
latch.countDown(); |
|
return false; |
|
}); |
|
} |
|
|
|
@Test |
|
public void wrappedFutureShouldPropagateExceptions() { |
|
String randomMessage = "Success: " + ThreadLocalRandom.current().nextInt(500); |
|
String randomExceptionMessage = "Failed: " + ThreadLocalRandom.current().nextInt(500); |
|
|
|
// Given |
|
CompletableFuture<String> completableFuture = new CompletableFuture<>(); |
|
|
|
// When (a future completes with a given result and wrapped future throws exception) |
|
completableFuture.complete(randomMessage); |
|
CompletableFuture<Boolean> wrappedFuture = Errors.<String, Boolean>whenComplete(completableFuture).wrap( |
|
(result, error) -> { |
|
throw new NoSuchMethodException(randomExceptionMessage); // Checked exception |
|
}); |
|
|
|
// Then (the error of the wrapped future is set to the wrapped future's result) |
|
assertThatThrownBy(() -> wrappedFuture.get(5, TimeUnit.SECONDS)) |
|
.hasCauseExactlyInstanceOf(NoSuchMethodException.class) |
|
.hasMessageContaining(randomExceptionMessage); |
|
} |
|
} |