Skip to main content

Soft assertions

By default, assertions fail fast—the first failed assertion stops test execution and reports the failure. Soft assertions allow you to collect multiple assertion failures and report them all at once, making it easier to fix multiple issues in a single test run.

Fail fast vs fail at end

Standard assertions stop at the first failure, hiding subsequent problems.

BookTest.java
import com.github.timtebeek.books.Book;
import org.junit.jupiter.api.Test;

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

class BookTest {

@Test
void verifyBook() {
Book book = new Book("Effective Java", "Joshua Bloch", 2001);

assertThat(book.getTitle()).contains("Ineffective"); // Fails here
assertThat(book.getAuthor()).contains("Blog"); // Never executed
assertThat(book.getYear()).isEven(); // Never executed
}
}
warning

With standard assertions, the test stops at the first failure. You only see that the title assertion failed, hiding the other two issues. This requires multiple test runs to discover and fix all problems.

Custom soft assertions

For domain objects that are tested frequently, you can create custom soft assertion classes to make tests more readable and reusable.

BookTest.java
import com.github.timtebeek.books.Book;
import org.assertj.core.api.SoftAssertions;
import org.junit.jupiter.api.Test;

class BookTest {

@Test
void verifyBook() {
Book book = new Book("Effective Java", "Joshua Bloch", 2001);

SoftAssertions.assertSoftly(softly -> {
softly.assertThat(book.getTitle()).as("title").contains("Effective");
softly.assertThat(book.getAuthor()).as("author").contains("Bloch");
softly.assertThat(book.getYear()).as("year").isLessThan(2003);
});
}
}
info

While this works, repeatedly asserting on the same object properties across multiple tests can become verbose.

Multiple failures reported

When soft assertions fail, all failures are collected and reported together.

BookTest.java
import com.github.timtebeek.books.Book;
import org.junit.jupiter.api.Test;

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

class BookTest {

@Test
void faultyBook() {
Book book = new Book("Effective Java", "Joshua Bloch", 2001);

assertThat(book.getTitle()).contains("Ineffective"); // Stops here
assertThat(book.getAuthor()).contains("Blog"); // Never runs
assertThat(book.getYear()).isEven(); // Never runs
}
}
danger

Output shows only the first failure:

Expected: "Effective Java" to contain "Ineffective"

You need to run the test three times to see all failures.