Testing Async / CompletableFuture Code
Fast recall
Quick revision
Core answer
Whether you understand the challenges of non-deterministic async execution in tests and how to avoid Thread.sleep()
Using Thread.sleep() to wait for async results — it makes tests slow and still flaky; use blocking get() or Awaitility instead
Mention Awaitility for testing @Async side effects (like database writes triggered asynchronously) without sleep, and how to test exception propagation in CompletableFuture
Interview-ready guide
Interview answer
For CompletableFuture, the future itself is your synchronization point — call .get(5, SECONDS) and assert on the result. No Thread.sleep() needed. For failures, future.get() wraps the exception in ExecutionException, so assert on the cause.
The harder case is @Async void methods. There's no future to wait on, so you need to observe a side effect. Awaitility is the standard tool: await().atMost(10, SECONDS).untilAsserted(() -> assertThat(...)). It polls the assertion until it passes or times out — adapting to actual execution speed instead of sleeping for an arbitrary duration.
Thread.sleep() is always wrong in tests. It's too slow (always waits the full duration) and too flaky (fails when CI is loaded). Every async test should use either the future's .get() or Awaitility.
Remember: @Async requires Spring's proxy, so these tests need @SpringBootTest with @EnableAsync.
Testing Async / CompletableFuture Code
Direct Answer
For CompletableFuture, call .get() or .join() in the test to block until the result is available, then assert on it. For @Async Spring methods, either use CountDownLatch/CompletableFuture to wait, or test the underlying method directly without the async wrapper in unit tests. For reactive code (Mono/Flux), use StepVerifier. Avoid Thread.sleep() — it makes tests slow and flaky.
Common Mistakes & Pitfalls
Using Thread.sleep() to wait for async results — it makes tests slow and still flaky; use blocking get() or Awaitility instead
Check your understanding
Answer these without looking back at the article.
- How do you test Spring WebFlux reactive pipelines with StepVerifier?
- How do you configure a test executor that is synchronous to simplify @Async tests?
- What is the difference between thenApply and thenCompose in CompletableFuture?
Related interview prep categories
1Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.