W3docs

Java JUnit Assertions

Verify behavior in JUnit 5 with assertEquals, assertTrue, assertThrows, assertAll, and more.

Java JUnit Assertions

An assertion is the moment a test stops describing and starts verifying — it states what the code should produce and fails the test if reality disagrees. JUnit 5 (the Jupiter API) collects every assertion as static methods on a single class, org.junit.jupiter.api.Assertions. Learn that handful of methods and you can express almost any expectation: equality, truth, nullness, sameness, thrown exceptions, timeouts, and grouped checks. This chapter tours the ones you reach for daily.

The mental model: a failed assertion fails the test

A JUnit test method runs top to bottom. Each assertion that holds is silent; the first one that does not hold throws an AssertionFailedError, which JUnit catches and records as a failure — the method stops there. So assertions are the test's exit points. The conventional argument order is expected first, actual second, and every method accepts an optional final message used only when the check fails:

import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

class CalculatorTest {
  @Test
  void addsTwoNumbers() {
    int result = 2 + 3;
    assertEquals(5, result, "2 + 3 should equal 5");
  }
}

You import the methods statically (import static ... Assertions.*) so the test body reads as plain English — assertEquals(...), not Assertions.assertEquals(...).

Equality, truth, and nullness

These four cover the large majority of real assertions:

MethodPasses when
assertEquals(expected, actual)expected.equals(actual) is true
assertNotEquals(unexpected, actual)the two are not equal
assertTrue(condition) / assertFalse(condition)the boolean is true / false
assertNull(obj) / assertNotNull(obj)the reference is / is not null
assertSame(expected, actual)both refer to the same object (==)
assertArrayEquals(expected, actual)arrays are equal element by element
assertEquals("HELLO", "hello".toUpperCase());
assertTrue(List.of(1, 2, 3).contains(2), "list should contain 2");
assertNull(map.get("missing"));
assertNotSame(new String("a"), new String("a")); // distinct objects
assertArrayEquals(new int[]{1, 2, 3}, computeRange(3));

assertEquals uses .equals(), so two different String objects with the same characters pass; assertSame uses ==, so they fail. Reach for assertSame only when object identity is what you mean to test.

Testing exceptions with assertThrows

A test sometimes asserts that code fails — that bad input throws. assertThrows takes the exception type and a lambda; it passes only if running the lambda throws that type (or a subtype), and it returns the caught exception so you can inspect its message:

@Test
void rejectsNullName() {
  IllegalArgumentException ex = assertThrows(
      IllegalArgumentException.class,
      () -> greet(null));
  assertEquals("name must not be null", ex.getMessage());
}

Its mirror image is assertDoesNotThrow, which fails if the lambda throws anything — useful for asserting that a previously buggy path now runs cleanly.

Grouping with assertAll

By default the first failed assertion ends the method, hiding any later problems. assertAll runs every contained assertion even when some fail, then reports all failures together — ideal for checking several properties of one object:

@Test
void buildsCompleteUser() {
  User u = User.of("[email protected]");
  assertAll("user",
      () -> assertEquals("[email protected]", u.email()),
      () -> assertTrue(u.isActive()),
      () -> assertNotNull(u.createdAt()));
}

If both the email and the active flag are wrong, one run tells you both — instead of fixing one, re-running, and discovering the next.

A worked example: a self-checking test run, no framework needed

The code runner has no JUnit on its classpath, so this program implements the same idea in plain Java: tiny assertEquals, assertTrue, assertThrows, and assertAll helpers that behave like Jupiter's — silent on success, loud on failure — driving a handful of methods under test and printing a runner-style tally at the end. The API you would actually write is in the static blocks above; this shows what those methods do.

java— editable, runs on the server

What to take from the run:

  • The passing checks produce no failure lines at all — only add(2,3) verified == 5 and tag conditions verified print, mirroring JUnit's rule that a satisfied assertion is silent and only failures speak.
  • assertThrows printed caught expected IllegalArgumentException: name must not be null, showing the pattern: the lambda must throw, the type must match, and the caught exception's message is yours to assert on next.
  • assertAll ran 3 checks, 0 failed confirms the grouping behavior — all three lambdas executed and were tallied together, which is exactly why assertAll surfaces every problem in one pass instead of stopping at the first.
  • The final SUMMARY -> passed: 7, failed: 0 counts seven individual assertions across the program (one equality, two booleans, one throws, and three inside assertAll), the same accounting a real runner reports — every assertX call is one verification.
  • Nothing here imported a test framework, yet the structure is identical to Jupiter: helpers that are quiet on success and explicit on failure. Swapping these for org.junit.jupiter.api.Assertions.* would change the imports, not the way you reason about each check.

Practice

Practice

In JUnit 5, what does 'assertAll' give you that a sequence of separate assertions does not?