What it is
Awaitility is a Java DSL (Domain Specific Language) for testing asynchronous code. It allows developers to wait for a certain condition to be met within a specified time period, making testing of async operations, background tasks, or event-driven systems more reliable and readable.
Awaitility allows you to define expectations using conditions, durations, and polling intervals. It integrates with JUnit, TestNG, and other test frameworks, making async testing straightforward.
Installation
Add dependency in pom.xml:
<dependency>
<groupId>org.awaitility</groupId>
<artifactId>awaitility</artifactId>
<version>4.2.0</version>
<scope>test</scope>
</dependency>Getting started
The smallest useful thing you can do with it, and what each part means.
import static org.awaitility.Awaitility.await;
import java.util.concurrent.TimeUnit;
boolean[] flag = {false};
new Thread(() -> {
Thread.sleep(1000);
flag[0] = true;
}).start();
await().atMost(5, TimeUnit.SECONDS).until(() -> flag[0]);import static org.awaitility.Awaitility.await;
import java.util.concurrent.atomic.AtomicInteger;
AtomicInteger counter = new AtomicInteger(0);
new Thread(() -> counter.incrementAndGet()).start();
await().untilAtomic(counter, val -> val > 0);Advanced usage
Where the library earns its place over a simpler alternative.
await().atMost(10, TimeUnit.SECONDS).pollInterval(500, TimeUnit.MILLISECONDS)
.until(() -> myService.isReady());await().atMost(5, TimeUnit.SECONDS).ignoreExceptions()
.until(() -> externalService.getData() != null);import static org.hamcrest.Matchers.*;
await().atMost(3, TimeUnit.SECONDS).until(() -> list.size(), equalTo(5));Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- ConditionTimeoutException
- Occurs when the expected condition is not met within the specified timeout. Verify the async logic or increase the timeout duration if necessary.
- IllegalStateException
- Occurs if Awaitility is misconfigured, e.g., negative timeouts or invalid poll intervals. Ensure proper API usage.
Best practices
- Avoid using Thread.sleep() in tests; prefer Awaitility for readability and reliability.
- Define reasonable timeouts to prevent tests from hanging indefinitely.
- Use atomic variables or thread-safe constructs for shared state in async tests.
- Integrate with JUnit or TestNG to run async tests seamlessly.
- Use polling intervals to balance responsiveness and CPU usage during waits.
Background
Why it exists, and what it was reacting to.
Testing asynchronous operations in Java can be challenging due to timing and concurrency issues. Awaitility was created to simplify this by providing a clean, readable API to wait for conditions without using Thread.sleep() or complex polling logic. It is widely used in unit tests, integration tests, and reactive systems testing.
