Close

AssertJ - Custom Assertions

[Last Updated: Mar 3, 2026]

While AssertJ's built-in assertions cover JDK types well, your domain objects benefit from tailored assertions. Instead of repeating assertThat(order.getStatus()).isEqualTo("SHIPPED") everywhere, you can build a OrderAssert class with a method isShipped(). This makes test intent crystal clear and reduces duplication.

Extending AbstractAssert

To create a custom assertion, extend AbstractAssert<SELF, ACTUAL> where SELF is your assertion class (for fluent chaining) and ACTUAL is the type under assertion. Provide a static factory method assertThat(ACTUAL) as the entry point.

Example

package com.logicbig.example;

import org.assertj.core.api.AbstractAssert;

public class PersonAssert extends AbstractAssert<PersonAssert, Person> {

    public PersonAssert(Person actual) {
        super(actual, PersonAssert.class);
    }

    public static PersonAssert assertThat(Person actual) {
        return new PersonAssert(actual);
    }

    public PersonAssert isAdult() {
        isNotNull();
        if (actual.age() < 18) {
            failWithMessage("Expected adult but age was %d",
                            actual.age());
        }
        return this;
    }

    public PersonAssert hasName(String name) {
        isNotNull();
        if (!actual.name().equals(name)) {
            failWithMessage("Expected name <%s> but was <%s>",
                            name,
                            actual.name());
        }
        return this;
    }
}

Test class

package com.logicbig.example;

import org.junit.jupiter.api.Test;

public class CustomAssertionsExample {

    @Test
    void myTest() {
        Person alice = new Person("Alice", 30);
        Person bob = new Person("Bob", 15);

        // using custom assertion
        PersonAssert.assertThat(alice).isAdult().hasName("Alice");
        System.out.println("Alice custom assertion passed");

        PersonAssert.assertThat(bob).hasName("Bob");
        System.out.println("Bob name check passed");

        // chaining custom assertions
        PersonAssert.assertThat(alice).isAdult().hasName("Alice");
        System.out.println("Chained custom assertions passed");
    }
}

Output

$ mvn clean test -Dtest=*
[INFO] Scanning for projects...
[INFO]
[INFO] -----------< com.logicbig.example:assertj-custom-assertions >-----------
[INFO] Building assertj-custom-assertions 1.0-SNAPSHOT
[INFO] from pom.xml
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- clean:3.2.0:clean (default-clean) @ assertj-custom-assertions ---
[INFO]
[INFO] --- resources:3.3.1:resources (default-resources) @ assertj-custom-assertions ---
[INFO] skip non existing resourceDirectory D:\example-projects\assertj\assertj-custom-assertions\src\main\resources
[INFO]
[INFO] --- compiler:3.11.0:compile (default-compile) @ assertj-custom-assertions ---
[INFO] No sources to compile
[INFO]
[INFO] --- resources:3.3.1:testResources (default-testResources) @ assertj-custom-assertions ---
[INFO] skip non existing resourceDirectory D:\example-projects\assertj\assertj-custom-assertions\src\test\resources
[INFO]
[INFO] --- compiler:3.11.0:testCompile (default-testCompile) @ assertj-custom-assertions ---
[INFO] Changes detected - recompiling the module! :source
[INFO] Compiling 3 source files with javac [debug target 17] to target\test-classes
[INFO]
[INFO] --- surefire:3.2.5:test (default-test) @ assertj-custom-assertions ---
[INFO] Using auto detected provider org.apache.maven.surefire.junitplatform.JUnitPlatformProvider
[WARNING] file.encoding cannot be set as system property, use <argLine>-Dfile.encoding=...</argLine> instead
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.logicbig.example.CustomAssertionsExample
Alice custom assertion passed
Bob name check passed
Chained custom assertions passed
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.062 s -- in com.logicbig.example.CustomAssertionsExample
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.215 s
[INFO] Finished at: 2026-03-03T14:10:34+08:00
[INFO] ------------------------------------------------------------------------

Conclusion

The output confirms that domain-specific assertion methods work correctly. By encapsulating the assertion logic in PersonAssert, the test code reads like a specification: assertThat(person).isAdult().hasName("Alice") is immediately understandable to any team member, regardless of AssertJ knowledge.

Example Project

Dependencies and Technologies Used:

  • assertj-core 3.27.7 (Rich and fluent assertions for testing in Java)
  • junit-jupiter-engine 6.0.2 (Module "junit-jupiter-engine" of JUnit)
  • JDK 17
  • Maven 3.9.11

AssertJ - Custom Assertions Select All Download
  • assertj-custom-assertions
    • src
      • test
        • java
          • com
            • logicbig
              • example
                • CustomAssertionsExample.java

    See Also

    Join