FutureUtils { public static <T> CompletableFuture<T> failedFuture(Throwable ex) { CompletableFuture<T> future = new CompletableFuture<>(); future.completeExceptionally(ex); return future; } private  FutureUtils(); static T block(CompletableFuture<? extends T> future); static CompletableFuture<T> wrapFutureForConditionalFallback(CompletableFuture<T> future,
                                                                            Predicate<? super Throwable> condition,
                                                                            Supplier<? extends CompletableFuture<T>> fallback); static CompletableFuture<Optional<T>> optionalFuture(CompletableFuture<? extends T> future); static CompletableFuture<T> orFallback(CompletableFuture<Optional<T>> future,
                                                      Supplier<? extends CompletableFuture<T>> fallback); static CompletableFuture<Optional<T>> orRetry(CompletableFuture<Optional<T>> future,
                                                             Supplier<? extends CompletableFuture<Optional<T>>> retry); static boolean isFailedRequestWithStatus(Throwable exception, int statusCode); static CompletableFuture<T> failedFuture(Throwable ex); static CompletableFuture<Collection<T>> sequence(Collection<CompletableFuture<T>> futures,
                                                                Function<Throwable, Boolean> exceptionHandler); static CompletableFuture<T> wrapInFuture(Callable<? extends T> action, String errMsg);  }
@Test public void testBlockFailedFuture() { IOException exception = new IOException("Failed future"); CompletableFuture<Integer> future = FutureUtils.failedFuture(exception); expectFailedFuture(future, exception); }