I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

In this tutorial, we’ll take a look at the AssertJ library, especially at defining and using conditions to create readable and maintainable tests.

AssertJ basics can be found here.

2. Class Under Test

Let’s have a look at the target class against which we’ll write test cases:

public class Member {
    private String name;
    private int age;

    // constructors and getters
}

3. Creating Conditions

We can define an assertion condition by simply instantiating the Condition class with appropriate arguments.

The most convenient way to create a Condition is to use the constructor that takes a Predicate as a parameter. Other constructors require us to create a subclass and override the matches method, which is less handy.

When constructing a Condition object, we must specify a type argument, which is the type of the value against which the condition is evaluated.

Let’s declare a condition for the age field of our Member class:

Condition<Member> senior = new Condition<>(
  m -> m.getAge() >= 60, "senior");

The senior variable now references a Condition instance which tests if a Person is senior based on its age.

The second argument to the constructor, the String “senior”, is a short description that will be used by AssertJ itself to build a user-friendly error message if the condition fails.

Another condition, checking whether a Person has the name “John”, looks like this:

Condition<Member> nameJohn = new Condition<>(
  m -> m.getName().equalsIgnoreCase("John"), 
  "name John"
);

4. Test Cases

Now, let’s see how to make use of Condition objects in our test class. Assume that the conditions senior and nameJohn are available as fields in our test class.

4.1. Asserting Scalar Values

The following test should pass as the age value is above the seniority threshold:

Member member = new Member("John", 65);
assertThat(member).is(senior);

Since the assertion with the is method passes, an assertion using isNot with the same argument will fail:

// assertion fails with an error message containing "not to be <senior>"
assertThat(member).isNot(senior);

Using the nameJohn variable, we can write two similar tests:

Member member = new Member("Jane", 60);
assertThat(member).doesNotHave(nameJohn);

// assertion fails with an error message containing "to have:\n <name John>"
assertThat(member).has(nameJohn);

The is and has methods, as well as the isNot and doesNotHave methods have the same semantics. Which we use is just a matter of choice. Nevertheless, it is recommended to pick the one that makes our test code more readable.

4.2. Asserting Collections

Conditions don’t work only with scalar values, but they can also verify the existence or non-existence of elements in a collection. Let’s take a look at a test case:

List<Member> members = new ArrayList<>();
members.add(new Member("Alice", 50));
members.add(new Member("Bob", 60));

assertThat(members).haveExactly(1, senior);
assertThat(members).doNotHave(nameJohn);

The haveExactly method asserts the exact number of elements meeting the given Condition, while the doNotHave method checks for the absence of elements.

The methods haveExactly and doNotHave are not the only ones working with collection conditions. For a complete list of those methods, see the AbstractIterableAssert class in the API documentation.

4.3. Combining Conditions

We can combine various conditions using three static methods of the Assertions class:

  • not – creates a condition that is met if the specified condition is not met
  • allOf – creates a condition that is met only if all of the specified conditions are met
  • anyOf – creates a condition that is met if at least one of the specified conditions is met

Here’s how the not and allOf methods can be used to combine conditions:

Member john = new Member("John", 60);
Member jane = new Member("Jane", 50);
        
assertThat(john).is(allOf(senior, nameJohn));
assertThat(jane).is(allOf(not(nameJohn), not(senior)));

Similarly, we can make use of anyOf:

Member john = new Member("John", 50);
Member jane = new Member("Jane", 60);
        
assertThat(john).is(anyOf(senior, nameJohn));
assertThat(jane).is(anyOf(nameJohn, senior));

5. Conclusion

This tutorial gave a guide to AssertJ conditions and how to use them to create very readable assertions in your test code.

The implementation of all the examples and code snippets can be found over on GitHub.

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS

Leave a Reply

Be the First to Comment!

avatar
  Subscribe  
Notify of