DeferredResult { public <U, V> DeferredResult<V> thenCombine(DeferredResult<? extends U> other, BiFunction<? super T, ? super U, ? extends V> fn) { return wrap(this.completableFuture.thenCombine(other.toCompletionStage(), fn)); } DeferredResult();  DeferredResult(CompletableFuture<T> completableFuture); static DeferredResult<U> completed(U value); static DeferredResult<U> failed(Throwable ex); static DeferredResult<Void> allOf(DeferredResult<?>... deferredResults); static DeferredResult<List<U>> allOf(List<DeferredResult<U>> deferredResults); static DeferredResult<?> anyOf(DeferredResult<?>... deferredResults); static DeferredResult<U> anyOf(List<DeferredResult<U>> deferredResults); DeferredResult<U> thenApply(Function<? super T, ? extends U> fn); DeferredResult<U> thenApplyAsync(Function<? super T, ? extends U> fn,
            Executor executor); DeferredResult<Void> thenAccept(Consumer<? super T> action); DeferredResult<Void> thenAcceptAsync(Consumer<? super T> action, Executor executor); DeferredResult<Void> thenRun(Runnable action); DeferredResult<Void> thenRunAsync(Runnable action, Executor executor); DeferredResult<V> thenCombine(DeferredResult<? extends U> other,
            BiFunction<? super T, ? super U, ? extends V> fn); DeferredResult<V> thenCombineAsync(DeferredResult<? extends U> other,
            BiFunction<? super T, ? super U, ? extends V> fn, Executor executor); DeferredResult<Void> thenAcceptBoth(DeferredResult<? extends U> other,
            BiConsumer<? super T, ? super U> action); DeferredResult<Void> thenAcceptBothAsync(DeferredResult<? extends U> other,
            BiConsumer<? super T, ? super U> action, Executor executor); DeferredResult<Void> runAfterBoth(DeferredResult<?> other, Runnable action); DeferredResult<Void> runAfterBothAsync(DeferredResult<?> other, Runnable action,
            Executor executor); DeferredResult<U> applyToEither(DeferredResult<? extends T> other,
            Function<? super T, U> fn); DeferredResult<U> applyToEitherAsync(DeferredResult<? extends T> other,
            Function<? super T, U> fn,
            Executor executor); DeferredResult<Void> acceptEither(DeferredResult<? extends T> other,
            Consumer<? super T> action); DeferredResult<Void> acceptEitherAsync(DeferredResult<? extends T> other,
            Consumer<? super T> action,
            Executor executor); DeferredResult<Void> runAfterEither(DeferredResult<?> other, Runnable action); DeferredResult<Void> runAfterEitherAsync(DeferredResult<?> other, Runnable action,
            Executor executor); DeferredResult<U> thenCompose(Function<? super T, ? extends DeferredResult<U>> fn); DeferredResult<U> thenComposeAsync(
            Function<? super T, ? extends DeferredResult<U>> fn,
            Executor executor); DeferredResult<T> exceptionally(Function<Throwable, ? extends T> fn); DeferredResult<T> whenComplete(BiConsumer<? super T, ? super Throwable> action); DeferredResult<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action,
            Executor executor); DeferredResult<U> handle(BiFunction<? super T, Throwable, ? extends U> fn); DeferredResult<U> handleAsync(BiFunction<? super T, Throwable, ? extends U> fn,
            Executor executor); T getNow(T valueIfAbsent); T getNow(Supplier<? extends T> valueSupplierIfAbsent); boolean isDone(); CompletionStage<T> toCompletionStage(); boolean complete(T value); boolean fail(Throwable ex); DeferredResult<T> whenCompleteNotify(Operation operation);  }
@Test public void testThenCombine() throws Throwable { TestContext ctx = new TestContext(1, TestContext.DEFAULT_WAIT_DURATION); DeferredResult<Integer> original = new DeferredResult<>(); DeferredResult<Integer> other = new DeferredResult<>(); DeferredResult<Integer> result = original .thenCombine(other, (x, y) -> x + y); result.whenComplete(ctx.getCompletionDeferred()); runAfter(10, () -> original.complete(1)); runAfter(20, () -> other.complete(2)); ctx.await(); Assert.assertEquals(3, result.getNow(0).intValue()); }