Unit Test with AssertJ in java Unit Test with AssertJ in java

assertThat() with AssertJ Assertions

Page content

In this tutorial, we’ll learn how to write efficient unit test cases in Java using AssertJ assertThat() assertions.

AssertJ

AssertJ is a Java library that provides a rich set of assertions similar to Hamcrest, which are very fluent to test the conditions on String, Number, Date, Time, Object, Collections, URI, File, etc.

AssertJ also supports soft assertions and writing custom messages in assertions. We will learn all these using examples.

You write unit tests with AssertJ using assertThat() statement followed by one or more assertions applicable to that class type.

Setup AssertJ

Import the required assertj-core dependency for Java using Maven (pom.xml) or Gradle (build.gradle), whichever you are using:-

<!-- add dependency in pom.xml -->
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <!-- use 2.9.1 for Java 7 projects -->
    <version>3.23.1</version>
    <scope>test</scope>
</dependency>
// add dependency in build.gradle
dependencies {
    testImplementation 'org.assertj:assertj-core:3.23.1'
}

Import AssertJ

Once you add the AssertJ dependency, you can import static assertThat method in the unit test class like this:-

import static org.assertj.core.api.Assertions.*;

We are ready to write unit test cases with AssertJ.

Using AssertJ Assertions

AssertJ provides assertions for most of the data types in Java e.g. Text (String), Number (Integer, Double, BigDecimal), Collection (List, Array, Set, Map), File, etc. See the complete list of assertions available in AssertJ core package

String assertions

AssertJ provides a variety of fluent assertions for String. Let’s look at them:-

String nullString = null;

// Assert that a String is not null
assertThat("notnull").isNotNull();

// Assert that a String is null or empty
assertThat(nullString).isNullOrEmpty();
assertThat("").isNullOrEmpty();

// Assert that a String is empty
assertThat("").isEmpty();

// Assert that a String is blank i.e. null, empty, or consists of one or more whitespace characters
assertThat(nullString).isBlank();
assertThat("").isBlank();
assertThat(" ").isBlank();
assertThat("  \t  ").isBlank();

// Assert that a String has given size
assertThat("abc").hasSize(3);
assertThat("abc").hasSizeLessThan(4);
assertThat("abc").hasSizeLessThanOrEqualTo(4);
assertThat("abc").hasSizeGreaterThan(2);
assertThat("abc").hasSizeGreaterThanOrEqualTo(2);

// Assert that a String has same size as other String, Array or List
assertThat("abc").hasSameSizeAs("def");
assertThat("abc").hasSameSizeAs(new char[] { 'd', 'e', 'f' });
assertThat("abc").hasSameSizeAs(Arrays.asList(1, 2, 3));

// Assert that a String has given number of lines
String multiLine = "First line\n" +
                    "Last line";
assertThat(multiLine).hasLineCount(2);

// Assert that two Strings are equal
assertThat("foo").isEqualTo("foo");

// Assert that two Strings are equal ignoring case
assertThat("FOO").isEqualToIgnoringCase("foo");

// Assert that a String is a number
assertThat("10").containsOnlyDigits();

// Assert that a String contains the given one or more Substrings
assertThat("Gandalf the grey").contains("alf");
assertThat("Gandalf the grey").contains("alf", "grey");
assertThat("Gandalf the grey").contains(Arrays.asList("alf", "grey"));
assertThat("Gandalf the grey").containsIgnoringCase("gandalf");

// Assert that a String starts with given Substring
assertThat("Lord of the Rings").startsWith("Lord");
assertThat("Lord of the Rings").startsWithIgnoringCase("lord");

// Assert that a String ends with given Substring
assertThat("Lord of the Rings").endsWith("Rings");
assertThat("Lord of the Rings").endsWithIgnoringCase("rings");

// Assert that a String is of given case
assertThat("abc").isLowerCase();
assertThat("camelCase").isMixedCase();
assertThat("ABC").isUpperCase();

For the complete list of String’s assertions, see AssertJ’s documentation AbstractCharSequenceAssert


Integer, Long, Double, Float, and BigDecimal assertions

AssertJ provides a variety of fluent assertions for Numbers.

  1. Test some common conditions on Integer, Long, Double, Float and BigDecimals:-

    // Assert that two Numbers are equal
    assertThat(1).isEqualTo(1);
    
    // Assert that a Number is 0
    assertThat(0).isZero();
    ssertThat(0.0).isZero();
    assertThat(BigDecimal.ZERO).isZero();
    
    // Assert that a Number is not 0
    assertThat(42).isNotZero();
    assertThat(3.14).isNotZero();
    assertThat(BigDecimal.ONE).isNotZero();
    
    // Assert that a Number is positive
    assertThat(42).isPositive();
    assertThat(3.14).isPositive();
    
    // Assert that a Number is negative
    assertThat(-42).isNegative();
    assertThat(-3.12).isNegative();
    
    // Assert that a Number is even
    assertThat(12).isEven();
    assertThat(-46).isEven();
    
    // Assert that a Number is odd
    assertThat(3).isOdd();
    assertThat(-17).isOdd();
    
    // Assert that a number is less than (or equal to) given number
    assertThat(1).isLessThan(2);
    assertThat(-2).isLessThan(-1);
    assertThat(1).isLessThanOrEqualTo(1);
    
    // Assert that a number is greater than (or equal to) given number
    assertThat(1).isGreaterThan(0);
    assertThat(-1).isGreaterThan(-2);
    assertThat(1).isGreaterThanOrEqualTo(1);
    
    // Assert that a number is within given range (inclusive)
    assertThat(1).isBetween(1, 3);
    
    // Assert that a number is within given range (exclusive)
    assertThat(2).isStrictlyBetween(1, 3);
    
  2. Compare two Double values with given precision:-

    assertThat(3.141592653589793238).isEqualTo(3.14, withPrecision(0.01)); // pass
    

    Here withPrecision(0.01) means to check the equality upto 2 decimal places

For the complete list of Number’s assertions, see AssertJ’s documentation AbstractIntegerAssert, AbstractLongAssert, AbstractDoubleAssert, AbstractFloatAssert, and AbstractBigDecimalAssert


LocalDate, LocalTime, and LocalDateTime assertions

AssertJ provides a variety of assertions to check the date, time, or date-time. Let’s look at them:-

  1. Assert that a LocalDate is not null and is today’s date:-

    assertThat(LocalDate.now()).isNotNull().isToday();
    
  2. Assert that a LocalDate has given Year, Month, and Day:-

    @Test
    public void givenLocalDate_whenHasGivenYearMonthAndDay_thenPass() {
        //ISO_LOCAL_DATE YYYY-MM-DD
        LocalDate date = LocalDate.parse("2020-01-15"); 
    
        assertThat(date).isEqualTo("2020-01-15");
    
        assertThat(date).hasYear(2020);
        assertThat(date).hasMonth(Month.JANUARY);
        assertThat(date).hasMonthValue(1);
        assertThat(date).hasDayOfMonth(15);
    }
    
  3. Assert that a LocalDate is before or after the given LocalDate:-

    @Test
    public void givenLocalDate_whenBeforeOrAfterGivenDate_thenPass(){
        LocalDate date = LocalDate.parse("2020-01-15");
        LocalDate nextDate = LocalDate.parse("2020-01-16");
    
        assertThat(date).isNotEqualTo(nextDate);
    
        assertThat(date).isBefore(nextDate);
        assertThat(date).isBeforeOrEqualTo(nextDate);
        assertThat(nextDate).isAfter(date);
        assertThat(nextDate).isAfterOrEqualTo(date);
    }
    
  4. Assert that a LocalDate is in the given Date range (inclusive):-

    @Test
    public void givenLocalDate_whenInGivenDateRangeInclusive_thenPass() {
        LocalDate localDate = LocalDate.now();
        assertThat(localDate).isBetween(localDate.minusDays(1), localDate.plusDays(1))
                .isBetween(localDate, localDate.plusDays(1))
                .isBetween(localDate.minusDays(1), localDate)
                .isBetween(localDate, localDate);
    
        LocalDate firstOfJanuary2000 = LocalDate.parse("2000-01-01");
        assertThat(firstOfJanuary2000).isBetween("1999-01-01", "2001-01-01")
                .isBetween("2000-01-01", "2001-01-01")
                .isBetween("1999-01-01", "2000-01-01")
                .isBetween("2000-01-01", "2000-01-01");
    }
    

    The start date and end date in .isBetween(startDate, endDate) are included in the range check.

  5. Assert that a LocalDate is in the given Date range (exclusive):-

    @Test
    public void givenLocalDate_whenInGivenDateRangeExclusive_thenPass() {
        LocalDate localDate = LocalDate.now();
        assertThat(localDate).isStrictlyBetween(localDate.minusDays(1), localDate.plusDays(1));
    
        LocalDate firstOfJanuary2000 = LocalDate.parse("2000-01-01");
        assertThat(firstOfJanuary2000).isStrictlyBetween("1999-01-01", "2001-01-01");
    }
    

    The start date and end date in .isStrictlyBetween(startDate, endDate) are excluded from the range check.

  6. Assert that a LocalTime matches conditions:-

    @Test
    public void givenLocalTime_whenMatchesConditions_thenPass() {
        // ISO_LOCAL_TIME HH::MM::SS
        LocalTime localTime = LocalTime.parse("10:00:00"); 
    
        assertThat(localTime).isNotNull().isEqualTo("10:00:00");
    
        assertThat(localTime).isBefore("14:00:00");
        assertThat(localTime).isAfter("09:00:00");
    }
    
  7. Assert that a LocalDateTime matches conditions:-

    @Test
    public void givenLocalDateTime_whenMatchesConditions_thenPass() {
        // ISO_LOCAL_DATE_TIME YYYY-MM-DDTHH:MM:SS
        LocalDateTime localDateTime = LocalDateTime.parse("2000-01-01T23:59:59"); 
    
        assertThat(localDateTime).isNotNull().isEqualTo("2000-01-01T23:59:59");
    
        assertThat(localDateTime).isBefore("2000-01-02T00:00:00");
        assertThat(localDateTime).isAfter("1999-01-01T00:00:00");
    }
    

Checkout AssertJ’s documentation for the full list of Date and Time assertions - AbstractLocalDateAssert, AbstractLocalTimeAssert, and AbstractLocalDateTimeAssert


Object assertions

  1. Assert that two objects are equal:-
    @Test
    public void givenTwoObjects_whenEquals_thenPass() {
        User user1 = User.builder().firstName("Adam").build();
        User user2 = User.builder().firstName("Adam").build();
        assertThat(user1).isEqualTo(user2);
    }
    
  2. Assert that an Object is null:-
    @Test
    public void givenObject_whenNull_thenPass() {
        User user = null;
        assertThat(user).isNull();
    }
    
  3. Assert that an Object is the same as the given instance
    @Test
    public void givenTwoObjects_whenSameInstance_thenPass() {
        User user = User.builder().firstName("Adam").build();
        assertThat(user).isSameAs(user);
    }
    
  4. Assert that two Objects have the same property values:-
    @Test
    public void givenTwoObjects_whenSamePropertyValues_thenPass() {
        User user1  = User.builder().firstName("Adam").age(22).isPremiumUser(true).build();
        User user2  = User.builder().firstName("Adam").age(22).isPremiumUser(true).build();
    
        assertThat(user1).usingRecursiveComparison().isEqualTo(user2);
    }
    
  5. Assert that two Objects have the same property values ignoring one or more given properties:-
    @Test
    public void givenTwoObjects_whenSamePropertyValuesExcludingIgnoredProps_thenPass() {
        User user1 = User.builder().firstName("Adam").age(22).isPremiumUser(true).build();
        User user2 = User.builder().firstName("Adam").age(18).isPremiumUser(false).build();
    
        assertThat(user1).usingRecursiveComparison()
                .ignoringFields("age", "isPremiumUser").isEqualTo(user2);
    }
    
  6. Assert that two Objects have the same property values ignoring one or more properties with null values:-
    @Test
    public void givenTwoObjects_whenSamePropertyValuesExcludingNullProps_thenPass() {
        User user1 = User.builder().firstName("Adam").age(22).isPremiumUser(true).build();
        User user2 = User.builder().firstName("Adam").age(null).isPremiumUser(null).build();
    
        assertThat(user1).usingRecursiveComparison()
                .ignoringExpectedNullFields()
                .isEqualTo(user2);
    }
    
  7. Assert that an Object has all the properties with non-null values:-
    @Test
    public void givenObject_whenHasNoNullProperties_thenPass() {
        User user  = User.builder().firstName("Adam").age(22).isPremiumUser(true).build();
        assertThat(user).hasNoNullFieldsOrProperties();
    }
    
  8. Assert that an Object has all the properties with null values:-
    @Test
    public void givenObject_whenHasAllNullProperties_thenPass() {
        User user  = User.builder().firstName(null).age(null).isPremiumUser(null).build();
        assertThat(user).hasAllNullFieldsOrProperties();
    }
    
  9. Assert that an Object has properties with the given names:-
    @Test
    public void givenObject_whenHasGivenProperties_thenPass() {
        User user  = User.builder().build();
        assertThat(user).hasFieldOrProperty("firstName");
        assertThat(user).hasFieldOrProperty("age");
        assertThat(user).hasFieldOrProperty("isPremiumUser");
    }
    
  10. Assert that an Object has properties with the given names and values:-
    @Test
    public void givenObject_whenHasPropertyWithGivenNameAndValue_thenPass() {
        User user  = User.builder().firstName("Adam").age(22).isPremiumUser(true).build();
        assertThat(user).hasFieldOrPropertyWithValue("firstName", "Adam");
        assertThat(user).hasFieldOrPropertyWithValue("age", 22);
        assertThat(user).hasFieldOrPropertyWithValue("isPremiumUser", true);
    
        assertThat(user).extracting("firstName").isEqualTo("Adam");
        assertThat(user).extracting("age").isEqualTo(22);
        assertThat(user).extracting("isPremiumUser").isEqualTo(true);
    
        assertThat(user).extracting("firstName", "age", "isPremiumUser").containsExactly("Adam", 22, true);
    }
    

For the complete list of Object’s assertions, see AssertJ’s documentation AbstractObjectAssert


List/Array assertions

AssertJ provides similar assertions for List and Array. Let’s look at the example where we are testing multiple conditions on List by chaining assertions one after another:-

@Test
public void givenList_whenMatchesConditions_thenPass(){
    List<String> list = Arrays.asList("lord", "of", "the", "rings");

    assertThat(list)
            .isNotNull()
            .isNotEmpty()
            .hasSize(4)
            .startsWith("lord")
            .contains("of")
            .contains("the", atIndex(2))
            .endsWith("rings")
            .containsSequence("of", "the");

    assertThat("lord").isIn(list);
}

Checkout AssertJ’s documentation for the full list of List’s assertions - AbstractListAssert


Map assertions

AsssertJ provides assertion for Map to check keys, values, and entries. Let’s look at them:-

  1. Assert that a Map is null or empty:-
    assertThat(new HashMap()).isNullOrEmpty();
    assertThat(new HashMap()).isEmpty();
    
  2. Assert that a Map contains the given Key, Value, and Entry using multiple chained assertions:-
    @Test
    public void givenMap_whenMatchesConditions_thenPass(){
        Map<String, String> myMap = new HashMap<>();
        myMap.put("myKey1", "myValue1");
        myMap.put("myKey2", "myValue2");
    
        assertThat(myMap)
                .isNotNull()
                .isNotEmpty()
                .hasSize(2)
                .containsKey("myKey1")
                .containsValue("myValue2")
                .containsEntry("myKey1", "myValue1")
                .contains(entry("myKey2", "myValue2"));
    }
    

Checkout AssertJ’s documentation for the full list of Map’s assertions - AbstractMapAssert


URI assertions

Let’s look at various assertions for http, https, mailto, and file URLs:-

@Test
public void givenURI_whenMatchesConditions_thenPass() throws URISyntaxException {
    assertThat(new URI("http://localhost:8080"))
            .hasScheme("http")
            .hasHost("localhost")
            .hasPort(8080)
            .hasPath("")
            .hasNoQuery()
            .hasNoParameters();

    assertThat(new URI("https://reqres.in/api/users?name=adam&page=1"))
            .hasScheme("https")
            .hasHost("reqres.in")
            .hasNoPort()
            .hasPath("/api/users")
            .hasQuery("name=adam&page=1")
            .hasParameter("name")
            .hasParameter("page", "1");

    assertThat(new URI("mailto:java-net@java.sun.com"))
            .hasScheme("mailto")
            .hasNoHost()
            .hasNoPort()
            .hasNoPath();

    assertThat(new URI("file:///home/user/Documents/hello-world.txt"))
            .hasScheme("file")
            .hasNoPort()
            .hasNoHost()
            .hasPath("/home/user/Documents/hello-world.txt");
}

Checkout AssertJ’s documentation for the full list of Java URI’s assertions - AbstractUriAssert


File assertions

AssertJ file provides a variety of assertions to check the File and Directory properties, size, path and it’s content. Let’s look at some examples:-

@Test
public void givenFile_whenMatchesConditions_thenPass() throws IOException {
    File tmpFile = File.createTempFile("tmp", "txt");
    File tmpDir = Files.createTempDirectory("tmpDir").toFile();

    assertThat(tmpFile)
            .exists()
            .isFile()
            .isReadable()
            .isWritable()
            .hasSize(0);

    assertThat(tmpDir)
            .exists()
            .isDirectory();
}

AssertJ has a lot more useful Java File and Directory assertions, check them out - AbstractFileAssert and AbstractFileSizeAssert


Soft assertions

AssertJ is hard assertion by default

AssertJ assertions are hard assertions by default, which means when you have multiple assertions in the test case and if one of them fails, it throws an exception and stops the execution there. Assertions after the failed assertion will not be executed. Let’s look at the below example of Hard Assertion:-

import static org.assertj.core.api.Assertions.*;

@Test
public void whenTestFail_hardAssert_stopExecution(){
	String text = "abc";

	assertThat(text).hasSize(3);   // pass
	assertThat(text).contains("z"); // fail - stop execution
	assertThat(text).startsWith("a");  // not executed
	assertThat(text).isEqualTo("def"); // not executed
}

An AssertionError is thrown upon execution like this:-

java.lang.AssertionError: 
Expecting actual:
  "abc"
to contain:
  "z" 
	at com.example.assertion.AssertJAssertThatTests.whenTestFail_hardAssert_stopExecution(AssertJAssertThatTests.java:463)

AssertJ soft assertion to the rescue

There are cases where we want to execute all the assertions in a test case regardless of failure and generate a report of total passed and failed assertions. This is known as Soft Assertion. Luckily AssertJ provides Assertions.SoftAssertions for this. Let’s look at the below example of Soft Assertion:-

import static org.assertj.core.api.Assertions.*;

@Test
public void whenTestFail_softAssert_continueExecution(){
	String text = "abc";
	SoftAssertions softly = new SoftAssertions();

	softly.assertThat(text).hasSize(3);  // pass
	softly.assertThat(text).contains("z");  // fail - continue execution
	softly.assertThat(text).startsWith("a");  // pass
	softly.assertThat(text).isEqualTo("def"); // fail

	softly.assertAll(); // must specify
}

Remember to specify softly.assertAll() after all your assertions, which tells AssertJ to execute all assertions regardless of failure.

You can also use the static method SoftAssertions.assertSoftly. The softly.assertAll() method will be called automatically after the lambda function completes. Check out the example below:-

@Test
public void whenTestFail_softAssert_continueExecution_lambda(){
    String text = "abc";
    SoftAssertions.assertSoftly(softly -> {
      softly.assertThat(text).hasSize(3);  // pass
      softly.assertThat(text).contains("z");  // fail - continue execution
      softly.assertThat(text).startsWith("a");  // pass
      softly.assertThat(text).isEqualTo("def"); // fail
    });
}

Here is the sample test report after execution:-

org.assertj.core.error.AssertJMultipleFailuresError: 
Multiple Failures (2 failures)
-- failure 1 --
Expecting actual:
  "abc"
to contain:
  "z" 
at AssertJAssertThatTests.whenTestFail_softAssert_continueExecution(AssertJAssertThatTests.java:474)
-- failure 2 --
expected: "def"
 but was: "abc"
at AssertJAssertThatTests.whenTestFail_softAssert_continueExecution(AssertJAssertThatTests.java:476)

Custom Message in assertion

You can also add a custom message in assertion using short-named as() method.

assertThat(object).as(customMessage).assertion...

Important note: You must call as() method before any actual assertion - otherwise it will not work, as assertion will fire first.

Let’s look at the example:-

@Test
public void givenObject_testAgeWithCustomMessage(){
    User user = new User("Joe", 22, true);
    assertThat(user.getAge()).as("check %s's age", user.getFirstName()).isEqualTo(18);
}

It logs the custom message in case of assertion failure, which is more readable:-

org.opentest4j.AssertionFailedError: [check Joe's age]
    expected: 18
    but was: 22

That’s all about AssertJ assertions. Thanks for Reading!