skip to content

JUnit Assertions

The core Jupiter assertions and their conventions: expected before actual, optional messages that can be lazy suppliers, and the delta form for floating-point comparison. Interviewers watch for argument order and for assertions that actually describe the failure.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

6

In JUnit 5's assertEquals, what is the argument order, and why does getting it wrong matter?

level: juniorimportance: must knowfreq 70%

answer

  1. expected first, actual second
  2. swap = correct pass/fail, wrong message
  3. 'expected: <X> but was: <Y>'
  4. same order for arrays/iterables/assertSame
  5. AssertJ assertThat(actual).isEqualTo(expected) avoids the trap

basics

~20 s

The order is assertEquals(expected, actual). The first value is what you expect, the second is what your code produced. Swapping them still passes or fails correctly, but the failure message reads backwards and confuses you.

solid answer

~40 s

JUnit 5's assertEquals takes the expected value first and the actual value second: assertEquals(expected, actual). The same convention applies to assertArrayEquals, assertIterableEquals, and assertSame. The assertion itself is symmetric, so a swapped call still passes when values match and fails when they differ. The danger is only in the failure message: JUnit prints 'expected: <X> but was: <Y>'. If you swap the arguments, the message labels your real result as 'expected' and your literal as 'actual', which sends you debugging in the wrong direction. Because the compiler cannot catch this, teams often add an assertion library like AssertJ (assertThat(actual).isEqualTo(expected)) whose fluent API makes the role of each value unambiguous and removes the ordering trap entirely.

go deeper

for a junior

State the order plainly: assertEquals(expected, actual), first is your expectation, second is the code's result.

for a middle

Explain that the call is symmetric for pass/fail but the failure MESSAGE is what breaks when swapped, and that the convention spans assertArrayEquals/assertIterableEquals/assertSame.

for a senior

Note the compiler can't enforce roles, recommend AssertJ for unambiguous reads, and connect clear messages to faster debugging in CI.

for a principal

Frame it as a team-wide readability/diagnostics standard: pick one assertion style, enforce via lint/review, and value failure-message quality as part of test maintainability.

## What an assertion is A **unit test** is a small program that runs a piece of your code and checks the result is what you intended. The check itself is performed by an **assertion**: a method that throws an error (failing the test) if a condition is not met, and does nothing (the test continues) if it is. **JUnit 5** (package `org.junit.jupiter.api`) is the standard testing framework for Java; its assertion methods live in the class `org.junit.jupiter.api.Assertions`. ## assertEquals and its signature The most common assertion is `assertEquals`. Its signature is: ``` assertEquals(expected, actual) ``` - **expected** — the value you, the test author, believe is correct. Usually a literal you typed (e.g. `5`, `"hello"`). - **actual** — the value your production code actually returned when run. JUnit compares the two using `.equals()` (or `==` for primitives) and the test passes when they are equal. ## Why order seems not to matter — but does Equality is **symmetric**: `a.equals(b)` is true exactly when `b.equals(a)` is true. So `assertEquals(5, total)` and `assertEquals(total, 5)` have the *same pass/fail outcome*. This is why a swapped call is not a compile error and the test still goes green or red correctly. The difference appears **only in the failure message**. When the values differ, JUnit produces text like: ``` org.opentest4j.AssertionFailedError: expected: <5> but was: <7> ``` It literally labels the first argument 'expected' and the second 'was' (actual). If you wrote `assertEquals(total, 5)` and `total` is 7, the message becomes 'expected: <7> but was: <5>' — claiming you expected 7 (your bug) and got 5 (your correct literal). That is backwards and will waste your debugging time. ## The same convention across the family Every comparing assertion in JUnit 5 uses **(expected, actual)**: `assertEquals`, `assertArrayEquals(expectedArray, actualArray)`, `assertIterableEquals(expectedList, actualList)`, and `assertSame(expectedRef, actualRef)`. Memorize one rule, apply it everywhere. ## How to stop making the mistake Because the compiler cannot enforce roles (both arguments are just `Object`), the common cure is a **fluent assertion library** such as **AssertJ**, where you write `assertThat(actual).isEqualTo(expected)`. Here the subject under test always comes first inside `assertThat(...)`, and the expected value goes inside `isEqualTo(...)`, so the roles are read in plain English and cannot be swapped silently.

  • If swapping arguments doesn't change pass/fail, why care at all?
    Because the diagnostic message labels the values 'expected' and 'actual'. A swap makes the message lie about which value was yours versus the code's, sending you debugging the wrong side and costing time on every failure.
  • How does AssertJ remove the ordering trap?
    Its fluent form assertThat(actual).isEqualTo(expected) puts the value under test inside assertThat() and the expectation inside isEqualTo(), so the roles read like English and can't be silently transposed.

saying these in an interview costs you the question

  • Claiming a swapped argument order makes the test pass when it should fail (it doesn't — only the message is wrong)
  • Saying assertEquals(actual, expected) is the JUnit convention
  • Thinking the compiler catches the swap

context

open as a page

How do assertArrayEquals and assertIterableEquals compare their inputs, and how does that differ from calling assertEquals on a List or array?

level: middleimportance: should knowfreq 45%

basics

~20 s

assertArrayEquals compares two arrays element by element (in order). assertIterableEquals walks two iterables (like Lists) and compares elements pairwise. assertEquals on raw arrays compares references, not contents, so it usually fails even when contents match.

open as a page

What is the difference between assertEquals and assertSame in JUnit 5, and when would you use each?

level: middleimportance: should knowfreq 55%

basics

~20 s

assertEquals checks that two objects are equal by value (using .equals()). assertSame checks they are the exact same object in memory (using ==). Use assertSame only when identity matters, like verifying a cache returns the same instance.

open as a page

How do you correctly assert equality of floating-point values in JUnit 5, and why is a plain assertEquals on doubles dangerous?

level: middleimportance: should knowfreq 50%

basics

~10 s

Use the overload assertEquals(expected, actual, delta), where delta is a small tolerance. Floating-point math has rounding errors, so 0.1 + 0.2 isn't exactly 0.3. The delta says 'close enough'.

open as a page

JUnit 5 assertions accept an optional failure message — what forms can it take, and why is the Supplier form preferred for expensive messages?

level: middleimportance: should knowfreq 40%

basics

~20 s

You can pass a String message as the last argument, shown only when the assertion fails. JUnit also accepts a Supplier<String> lambda; the lambda runs only on failure, so a costly message isn't built every time the test passes.

open as a page

What problem does assertAll solve compared to a sequence of separate assertions, and when should you reach for it?

level: seniorimportance: should knowfreq 38%

basics

~20 s

With separate assertions, the first failure stops the test, hiding later problems. assertAll runs a group of assertions together and reports ALL failures at once, so one test run tells you everything that's wrong instead of one issue at a time.

open as a page