Assertions are the heart of JUnit testing. Without them, you are just running code without checking if it does the right thing. JUnit 5 provides a rich set of assertion methods that let you verify everything from simple equality to complex exception handling.
Basic Assertions
Let us start with the assertions you will use most often:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class AssertionsDemoTest {
@Test
void assertEqualsDemo() {
assertEquals(4, 2 + 2);
assertEquals("hello", "hello");
assertEquals(3.14, 3.14, 0.001); // with delta for floating point
}
@Test
void assertNotEqualsDemo() {
assertNotEquals(5, 2 + 2);
assertNotEquals("hello", "world");
}
@Test
void assertTrueDemo() {
assertTrue(5 > 3);
assertTrue("hello".contains("ell"));
}
@Test
void assertFalseDemo() {
assertFalse(5 < 3);
assertFalse("hello".contains("xyz"));
}
@Test
void assertNullDemo() {
String nothing = null;
assertNull(nothing);
String something = "hello";
assertNotNull(something);
}
}
Custom Failure Messages
All assertions accept an optional message parameter. This is incredibly useful when a test fails because it tells you exactly what went wrong:
@Test
void shouldCalculateTotal() {
int total = calculateTotal(10, 20);
assertEquals(35, total,
"calculateTotal should return sum of inputs");
}
When this test fails, you get:
org.opentest4j.AssertionFailedError:
calculateTotal should return sum of inputs
expected: <35> but was: <30>
Without the message, you would just see "expected 35 but was 30" โ helpful, but the message makes it crystal clear what the intention was.
Array Assertions
Comparing arrays requires special handling because assertEquals does not
work on arrays directly (it would compare references, not contents):
@Test
void shouldCompareArrays() {
int[] expected = {1, 2, 3};
int[] actual = {1, 2, 3};
assertArrayEquals(expected, actual);
}
@Test
void shouldCompareStringArrays() {
String[] expected = {"hello", "world"};
String[] actual = {"hello", "world"};
assertArrayEquals(expected, actual);
}
Exception Assertions
Testing exceptions is a common need. Use assertThrows:
@Test
void shouldThrowOnDivisionByZero() {
Calculator calc = new Calculator();
assertThrows(ArithmeticException.class,
() -> calc.divide(10, 0));
}
@Test
void shouldThrowWithMessage() {
Calculator calc = new Calculator();
ArithmeticException exception = assertThrows(
ArithmeticException.class,
() -> calc.divide(10, 0)
);
assertEquals("Cannot divide by zero", exception.getMessage());
}
Group Assertions
When you need to check multiple conditions, use assertAll:
@Test
void shouldVerifyUser() {
User user = new User("John", "john@example.com", 25);
assertAll("user properties",
() -> assertEquals("John", user.getName()),
() -> assertEquals("john@example.com", user.getEmail()),
() -> assertEquals(25, user.getAge())
);
}
The advantage of assertAll over multiple assertEquals calls
is that all assertions run even if some fail. Without assertAll,
the first failure stops execution and you do not see the other failures.
Timeout Assertions
You can assert that a method completes within a time limit:
@Test
void shouldCompleteQuickly() {
assertTimeout(Duration.ofSeconds(1), () -> {
// This should finish within 1 second
int result = calculateExpensiveOperation();
assertEquals(42, result);
});
}
Line-Up: JUnit 4 vs JUnit 5 Assertions
+------------------+------------------------+------------------------+
| Purpose | JUnit 4 | JUnit 5 |
+------------------+------------------------+------------------------+
| Equal | assertEquals | assertEquals |
| Not Equal | assertNotEquals | assertNotEquals |
| True | assertTrue | assertTrue |
| False | assertFalse | assertFalse |
| Null | assertNull | assertNull |
| Not Null | assertNotNull | assertNotNull |
| Arrays Equal | assertArrayEquals | assertArrayEquals |
| Exception | @Test(expected=...) | assertThrows(...) |
| Timeout | @Test(timeout=...) | assertTimeout(...) |
| Fail | fail() | fail() |
+------------------+------------------------+------------------------+
The JUnit 5 assertions are more powerful and flexible. The exception testing approach in particular is much better โ you can inspect the exception, not just check its type.