Reputation: 49
I'm using CompletableFuture Java8 class to make network calls asynchronously in Java, specifically using the supplyAsync()
method. It's working great. I've figured out that I can unit test the "happy path" scenarios using CompletableFuture.completedFuture()
. What I'm trying to figure out is how to unit test (if possible) the cases where an exception (i.e. CompletionException
, InterruptedException
, or ExecutionException
) is thrown during the async task.
https://www.baeldung.com/java-completablefuture was a starting point and useful source but doesn't address this question.
My first approach does not compile:
final CompletableFuture<ResponseType> completableFutureException =
CompletableFuture.completedFuture(new InterruptedException());
My second approach predictably generates a ClassCastException
at runtime:
final CompletableFuture completableFutureException =
CompletableFuture.completedFuture(new InterruptedException());
java.lang.ClassCastException: java.lang.InterruptedException cannot be cast to ResponseType
It also sounds like the CompletableFuture<U> newIncompleteFuture()
method in Java9 might help - alas, we are stuck on Java8 for the moment. If Java9 would help me here, I'd still appreciate knowing.
As I've said, I'd like to figure out if there is a reasonable way to test this in Java8 (preferably without using PowerMock, as we've had trouble getting that to play nicely with Gradle). If this really just isn't unit-testable, I can accept that and move on.
Upvotes: 0
Views: 4919
Reputation: 9043
Java 9 introduced a new method failedFuture to meet this need. You can easily create your own equivalent method if you're running Java 8.
public static <T> CompletableFuture<T> failedFuture(Throwable ex) {
// copied from Java 9 https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/concurrent/CompletableFuture.html#failedFuture(java.lang.Throwable)
CompletableFuture<T> f = new CompletableFuture<>();
f.completeExceptionally(ex);
return f;
}
CompletableFuture<ResponseType> failure = failedFuture(new InterruptedException());
Alternatively you can use supplyAsync:
CompletableFuture<ResponseType> failure = CompletableFuture.supplyAsync(() -> {throw new InterruptedException();})
Upvotes: 1