Fluent assertions with AssertJ

Writing tests is essential, but writing good tests is hard. It is specially hard to write good and readable assertions.

When you use JUnit you have methods such as assertEquals or assertTrue. Both these methods work fine and do what they should do. However if the assertions get more complex they might not be as handy as assertions could be.

AssertJ is a library that gives you the possibility to write fluent assertions in your tests.

The following example implementation of unit tests show the difference between AssertJ and standard JUnit tests.

@Test
public void testZooJunit() {
    List<Animal> expectedAnimals = new ArrayList<>();
    expectedAnimals.add(dog);
    expectedAnimals.add(monkey);
    expectedAnimals.add(lion);
    assertEquals(expectedAnimals, zoo.animals);
}

@Test
public void testZoo() {
    assertThat(zoo.animals).containsOnly(dog, monkey, lion);
}

As you can see the AssertJ test tells you in much less code exactly was it does. This make such tests a lot more readable.

Besides the standard assertions AssertJ also provides a way to generate customized assertion classes. This can either be done via the command line or your build tool, such as Maven. Such a generated assertion class can look like this:

/** ... */
public class AnimalAssert extends AbstractAssert<AnimalAssert, Animal> {
    // Constructor
    /** ... */
    public static AnimalAssert assertThat(Animal actual) {
        return new AnimalAssert(actual);
    }

    /** ... */
    public AnimalAssert hasName(String name) {
        // check that actual Animal we want to make assertions on is not null.     isNotNull();
        // overrides the default error message with a more explicit one String    
        assertjErrorMessage = "\nExpecting name of:\n <%s>\nto be:\n <%s>\nbut was:\n <%s>";
        // null safe check
        String actualName = actual.name;
        if (!Objects.areEqual(actualName, name)) {
            failWithMessage(assertjErrorMessage, actual, name, actualName);
        }
        // return the current assertion for method chaining return this;
    }
}

With these generated classes you can do assertions that are customized for your objects. Of course, you can implement your own assertion methods in these classes, too. An example of a test that uses the AnimalAssert class can look like this:

import static net.devcouch.assertj.AnimalAssert.assertThat;
public class AnimalTest {
    // setup
    @Test public void testName() {
        assertThat(animal).hasName(ANIMAL_NAME);
    }
}

If you want to know more please read the docs or head over to GitHub and check out my AssertJ showcase.