In this post we’re going to figure out how AssertJ can make our life easier if we need to validate complex objects in Java.

Let’s start with the simple object Author that has only 2 fields

public class Author {

    private String firstName;
    private String lastName;

    public Author(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
    ...
    public String toString() {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        return gson.toJson(this);
    }
}

AssertJ maven dependency

<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <!-- use 2.9.0 for Java 7 projects -->
    <version>3.9.0</version>
    <scope>test</scope>
</dependency>

Regular objects validation in Java with AssertJ

SoftAssertions assertions = new SoftAssertions();

Author expectedAuthor = new Author("John", "Doe");
Author actualAuthor = new Author("John", "Doe");

assertions.assertThat(actualAuthor.getFirstName()).as("firstName")
		.isEqualTo(expectedAuthor.getFirstName());
assertions.assertThat(actualAuthor.getLastName()).as("lastName")
		.isEqualTo(expectedAuthor.getLastName());

assertions.assertAll();

see AssertJ. Custom fail messages (assertion messages)

Validate objects with isEqualToComparingFieldByField. AssertJ

SoftAssertions assertions = new SoftAssertions();

Author expectedAuthor = new Author("John", "Doe");
Author actualAuthor = new Author("John", "Doe");

assertions.assertThat(actualAuthor).as("Author")
		.isEqualToComparingFieldByField(expectedAuthor);

assertions.assertAll();

Even for simple objects like this we already have some benefits - less code.

Let’s see how failures look like if something is wrong with our object, for example actualAuthor = new Author("Jane", "Doe");.

The following assertion failed:
1) [Author] 
Expecting value <"John"> in field <"firstName"> but was <"Jane"> in <{
  "firstName": "Jane",
  "lastName": "Doe"
}>.
Comparison was performed on all fields

Very informative and readable, isn’t it?

Validate objects with isEqualToComparingFieldByFieldRecursively. AssertJ

In the real world we have to validate objects much more complex then the example above.

Let’s make it more complex

public class Book {

    private String title;
    private Author author;
    private int year;
    private int pages;

    public Book(String title, Author author, int year, int pages) {
        this.title = title;
        this.author = author;
        this.year = year;
        this.pages = pages;
    }
    ...
    public String toString() {
        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        return gson.toJson(this);
    }
}

Our test looks like this

SoftAssertions assertions = new SoftAssertions();

Book expectedBook = new Book("Book title", new Author("John", "Doe"), 2018, 300);
Book actualBook = new Book("Book title", new Author("John", "Doe"), 2018, 300);

assertions.assertThat(expectedBook).as("Book")
        .isEqualToComparingFieldByFieldRecursively(actualBook);

assertions.assertAll();

Let’s see how the failure would look like if something is wrong with actualBook, for example actualBook = new Book("Book title", new Author("Jane", "Doe"), 2018, 300);

The following assertion failed:
1) [Book] 
Expecting:
  <{
  "title": "Book title",
  "author": {
    "firstName": "John",
    "lastName": "Doe"
  },
  "year": 2018,
  "pages": 300
}>
to be equal to:
  <{
  "title": "Book title",
  "author": {
    "firstName": "Jane",
    "lastName": "Doe"
  },
  "year": 2018,
  "pages": 300
}>
when recursively comparing field by field, but found the following difference(s):

Path to difference: <author.firstName>
- expected: <"Jane">
- actual  : <"John">

You have everything to quckly understand why it’s failing and what is wrong with the object that you validate.

Validate objects with isEqualToIgnoringGivenFields. AssertJ

What if we accept any author’s firstName but expect the exact lastName (in our case “Doe”)? In that case the test would look like this

SoftAssertions assertions = new SoftAssertions();

Book expectedBook = new Book("Book title", new Author("John", "Doe"), 2018, 300);
Book actualBook = new Book("Book title", new Author("Jane", "Doe"), 2018, 300);

assertions.assertThat(expectedBook).as("Book")
        .isEqualToIgnoringGivenFields(actualBook, "author");
assertions.assertThat(expectedBook.getAuthor()).as("Book.Author")
        .isEqualToIgnoringGivenFields(actualBook.getAuthor(), "firstName");

assertions.assertAll();

Validate objects with isEqualToComparingOnlyGivenFields. AssertJ

There is another way to that with isEqualToComparingOnlyGivenFields.

SoftAssertions assertions = new SoftAssertions();

Book expectedBook = new Book("Book title", new Author("John", "Doe"), 2018, 300);
Book actualBook = new Book("Book title", new Author("Jane", "Doe"), 2018, 300);

assertions.assertThat(expectedBook).as("Book")
        .isEqualToComparingOnlyGivenFields(actualBook, "title", "year", "pages");
assertions.assertThat(expectedBook.getAuthor()).as("Book.Author")
        .isEqualToComparingOnlyGivenFields(actualBook.getAuthor(), "lastName");

assertions.assertAll();

Try it - you’ll love it.


You may also find these posts interesting: