简体   繁体   中英

Java8 UnitTesting CompletableFuture Exception

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 (ie 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.

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();})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM