Assertions
An assertion is a method that checks a condition and stops the test with an error if the condition is false. All JUnit assertions are static methods of the org.junit.jupiter.api.Assertions class. Besides assertEquals there are a dozen more; this lesson covers the ones you need every day.
The blog post
From here on, some examples test the blog. A post is a record in src/main/java/com/example/blog/Post.java:
// src/main/java/com/example/blog/Post.java
package com.example.blog;
public record Post(Long id, String title, String author, boolean published) {
public Post publish() {
return new Post(id, title, author, true);
}
}A new post has no id yet and is a draft. publish() does not change the record, it returns a published copy.
Main assertions
| Assertion | Passes when |
|---|---|
assertEquals(expected, actual) | The values are equal by equals() |
assertNotEquals(a, b) | The values differ |
assertTrue(condition) / assertFalse(condition) | The condition is true / false |
assertNull(value) / assertNotNull(value) | The value is null / not null |
assertSame(a, b) | It is the same object, a == b |
assertIterableEquals(expected, actual) | Two collections have equal elements in the same order |
fail("message") | Never: fails the test unconditionally |
// src/test/java/com/example/blog/PostTest.java
package com.example.blog;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class PostTest {
@Test
void newPostIsDraft() {
Post post = new Post(null, "Hello, JUnit", "anna", false);
assertNull(post.id());
assertFalse(post.published());
}
@Test
void publishReturnsPublishedCopy() {
Post draft = new Post(1L, "Hello, JUnit", "anna", false);
Post published = draft.publish();
assertNotNull(published);
assertTrue(published.published(), "publish() must set the flag");
assertFalse(draft.published(), "the original post must not change");
}
}The import with * brings in all assertions at once. Both tests pass.
A message for the failure
The last parameter of any assertion is a message. Without it, assertTrue only says expected: <true> but was: <false>; with it, the reason is clear:
org.opentest4j.AssertionFailedError: publish() must set the flag ==> expected: <true> but was: <false>If building the message is expensive, pass a lambda: () -> "post " + post — it is called only when the check fails.
Several checks at once: assertAll
Normally the test stops at the first failed assertion, and you do not know about the others. assertAll runs every check and reports all failures together:
// src/test/java/com/example/blog/PostTest.java
@Test
void publishKeepsOtherFields() {
Post published = new Post(1L, "Hello, JUnit", "anna", false).publish();
assertAll(
() -> assertEquals(1L, published.id()),
() -> assertEquals("Hello, JUnit", published.title()),
() -> assertEquals("anna", published.author()),
() -> assertTrue(published.published())
);
}If the test expected the title "Hello" and the author "oleg", the report lists both failures:
org.opentest4j.MultipleFailuresError:
Multiple Failures (2 failures)
org.opentest4j.AssertionFailedError: expected: <Hello> but was: <Hello, JUnit>
org.opentest4j.AssertionFailedError: expected: <oleg> but was: <anna>Collections
assertIterableEquals compares element by element and tells you where the difference is:
// src/test/java/com/example/blog/PostTest.java
assertIterableEquals(List.of("First", "Second"), List.of("First", "Third"));org.opentest4j.AssertionFailedError: iterable contents differ at index [1], expected: <Second> but was: <Third>Common mistake
BigDecimal.equals() compares not only the value but also the scale — the number of digits after the point. 36 and 36.00 are different for it:
// src/test/java/com/example/shop/PriceCalculatorTest.java
assertEquals(new BigDecimal("36"), calculator.total(new BigDecimal("12"), 3));org.opentest4j.AssertionFailedError: expected: <36> but was: <36.00>Write the expected amount with the same scale as the code returns ("36.00"), or compare with compareTo: assertEquals(0, expected.compareTo(actual)). AssertJ has a ready-made isEqualByComparingTo for this.