1

There are 2 completable futures cf1 and cf2 defined as follows:

CompletableFuture<Boolean> cf1 = CompletableFuture.completedFuture(true);

CompletableFuture<Boolean> cf2 = CompletableFuture.completedFuture(true);

Technically, one could do:

var result1 = cf1.get();
var result2 = cf2.get();

assertThat(result1).isEqualTo(result2);

For example, if there was only one future, we could do the following:

assertThat(cf1)
    .succeedsWithin(Duration.ofSeconds(1))
    .isEqualTo(true);

Is there a more idiomatic way to compare the two futures against each other? Note that while the example here uses CompletableFuture<Boolean>, the Boolean can be replaced with any class.

Bhushan
  • 590
  • 1
  • 7
  • 23

2 Answers2

1

If you are interested only in value comparison, passing cf2.get() as argument of isEqualTo should be enough:

CompletableFuture<Boolean> cf1 = CompletableFuture.completedFuture(true);
CompletableFuture<Boolean> cf2 = CompletableFuture.completedFuture(true);

assertThat(cf1)
  .succeedsWithin(Duration.ofSeconds(1))
  .isEqualTo(cf2.get());

The only downside is that get() can potentially throw ExecutionException and InterruptedException so they need to be declared in the test method signature.

If type-specific assertions are needed, succeedsWithin(Duration, InstanceOfAssertFactory) can help:

assertThat(cf1)
  .succeedsWithin(Duration.ofSeconds(1), InstanceOfAssertFactories.BOOLEAN)
  .isTrue(); // hardcoded check to show type-specific assertion
Stefano Cordio
  • 1,687
  • 10
  • 20
  • Thanks, Stefano. The downside that you mention is the exact thing that I'm trying to avoid. I would like to avoid `.get()`. For a simple boolean, hard-coding to `.isTrue()` (or false) is possible, but as I said, I'm comparing two objects here. – Bhushan Sep 19 '22 at 04:24
0

What about composing the two futures into one that completes successfully with a value of true if and only if both individual futures complete successfully with the same value? You could e.g. use thenCompose followed by thenApply:

CompletableFuture<Boolean> bothEqual = cf1.thenCompose(b1 -> cf2.thenApply(b2 -> b1 == b2));

If the sequential execution from this solution is problematic, you can parallelize by implementing a helper function alsoApply and use that one instead of thenCompose. See this answer for more details.

michid
  • 10,536
  • 3
  • 32
  • 59