VOOZH about

URL: https://www.javacodegeeks.com/2014/04/using-assertj-and-awaitility-together-thanks-to-java-8-and-lambdas.html

⇱ Using AssertJ and Awaitility together thanks to Java 8 and lambdas


AssertJ and Awaitility are two of my favorites tools using in automatic code testing. Unfortunately until recently it was not possible to use it together. But then Java 8 entered the game and several dozens lines of code was enough to make it happen in Awaility 1.6.0.

πŸ‘ awaitility_logo_red_small

 
AssertJ provides a rich set of assertions with very helpful error messages, all available though the fluent type aware API. Awaitility allows to express expectations of asynchronous calls in a concise and easy to read way leveraging an active wait pattern which shortens the duration of tests (no more sleep(5000)!).

The idea to use it together came into my mind a year ago when I was working on an algo trading project using Complex event processing (CEP) and I didn’t like to learn Hamcrest assertion just for asynchronous tests with Awaitility. I was able to do a working PoC, but it required to make some significant duplication in AssertJ (then FEST Assert) code and I shelved the idea. A month ago I was preparing my presentation about asynchronous code testing for the 4Developers conference and asked myself a question: How Java 8 could simplify the usage of Awaitility?

For the few examples I will use asynchronousMessageQueue which can be used to send ping request and return number of received packets. One of the ways to test it with Awaitility in Java 7 (besides proxy based condition) is to create a Callable class instance:

@Test
 public void shouldReceivePacketAfterWhileJava7Edition() {
 //when
 asynchronousMessageQueue.sendPing();
 //then
 await().until(receivedPackageCount(), equalTo(1));
 }

 private Callable<Integer> receivedPackageCount() {
 return new Callable<Integer>() {
 @Override
 public Integer call() throws Exception {
 return asynchronousMessageQueue.getNumberOfReceivedPackets();
 }
 };
 }

where equalTo() is a standard Hamcrest matcher.

The first idea to reduce verbosity is to replace Callable with a lambda expression and inline the private method:

@Test
 public void shouldReceivePacketAfterWhile() {
 //when
 asynchronousMessageQueue.sendPing();
 //then
 await().until(() -> asynchronousMessageQueue.getNumberOfReceivedPackets(), equalTo(1));
 }

Much better. Going forward lambda expression can be replaced with a method reference:

@Test
 public void shouldReceivePacketAfterWhile() {
 //when
 asynchronousMessageQueue.sendPing();
 //then
 await().until(asynchronousMessageQueue::getNumberOfReceivedPackets, equalTo(1));
 }

Someone could go even further and remove Hamcrest matcher:

@Test
 public void shouldReceivePacketAfterWhile() {
 //when
 asynchronousMessageQueue.sendPing();
 //then
 await().until(() -> asynchronousMessageQueue.getNumberOfReceivedPackets() == 1); //poor error message
 }

but while it still works the error message becomes much less meaningful:

ConditionTimeoutException: Condition with lambda expression in
AwaitilityAsynchronousShowCaseTest was not fulfilled within 2 seconds.

instead of very clear:

ConditionTimeoutException: Lambda expression in AwaitilityAsynchronousShowCaseTest
that uses AbstractMessageQueueFacade: expected <1> but was <0> within 2 seconds.>

The solution would be to use AssertJ assertion inside lambda expression:

@Test
 public void shouldReceivePacketAfterWhileAssertJEdition() {
 //when
 asynchronousMessageQueue.sendPing();
 //then
 await().until(() -> assertThat(asynchronousMessageQueue.getNumberOfReceivedPackets()).isEqualTo(1));
 }

and thanks to the new AssertionCondition initially hacked within a few minutes it became a reality in Awaitility 1.6.0. Of course AssertJ fluent API and meaningful failure messages for different data types are preserved.

As a bonus all assertions that throw AssertionError (so particularly TestNG and JUnit standard assertions) can be used in the lambda expression as well (but I don’t know anyone who came back to β€œstandard” assertion knowing the power of AssertJ).

The nice thing is that the changes itself leverage Runnable class to implement lambdas and AssertJ support and Awaitility 1.6.0 is still Java 5 compatible. Nevertheless for the sake of readability it is only sensible to use the new constructions in Java 8 based projects.

Btw, here are the β€œslides” from my presentation at 4Developers.

Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Thank you!

We will contact you soon.

πŸ‘ Photo of Marcin Zajaczkowski
Marcin Zajaczkowski
April 30th, 2014Last Updated: April 29th, 2014
0 277 2 minutes read

Marcin Zajaczkowski

Marcin is an experienced architect who specializes in creating high quality software. Being under the impression of the Agile methodologies and the Software Craftsmanship movement, he believes in the value of good, testable and maintainable code. He aims to forge good software that makes the client delighted and the team proud of how the code itself looks.In his teaching, as a conference speaker, college lecturer, IT coach and trainer, he shows how to guide software development effectively using tests (with TDD, pair programming, Clean Code, design patterns, etc.) and maintaining a quality-oriented development environment (with CI, Sonar, automatic deployment, etc.).He is also a FOSS projects author and contributor, a Linux enthusiast.
Subscribe

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Back to top button
Close
wpDiscuz