In JUnit 5, what is the difference between an assumption (assumeTrue) and an assertion (assertTrue)? What happens to a test when each one fails?
answer
- Assertion fails = RED; assumption fails = SKIPPED/green
- Assertions package vs Assumptions package
- Assumption throws TestAbortedException
- Assertion = code under test; assumption = precondition/environment
- Code after a failed assumption does not run
basics
~20 sAn assertion checks the result you are testing: if it is false, the test FAILS. An assumption checks a precondition: if it is false, the test is SKIPPED (aborted), not failed. So a failed assumption is treated like a test that did not run.
solid answer
~40 sAssertions and assumptions both take a boolean, but they answer different questions. An assertion (assertTrue/assertEquals) verifies the behavior under test; if it is false, JUnit marks the test as FAILED and the build goes red. An assumption (assumeTrue/assumeFalse) verifies a precondition the test needs to be meaningful; if it is false, JUnit throws a TestAbortedException and the test is reported as SKIPPED/ABORTED, not failed. The build stays green. The intent matters: use assumptions for environmental gates ('only run this if we are on Linux' or 'only if a DB env var is set'), and assertions for the thing you actually want to prove. Code that appears AFTER a failed assumption does not execute, because the abort exception unwinds the test method immediately.
code
java · 12 linesimport static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
import org.junit.jupiter.api.Test;
class PaymentTest {
@Test
void chargesInProductionOnly() {
assumeTrue("prod".equals(System.getenv("STAGE")));
// SKIPPED (not failed) when STAGE != prod
assertEquals(100, charge(100)); // the actual claim about behavior
}
}go deeper
Knows assertion failure = test fails (red), assumption failure = test skipped (green), and that they come from different classes.
Can articulate the intent split (precondition vs behavior), names TestAbortedException vs AssertionFailedError, and knows the rest of the method is skipped after a failed assumption.
Explains when to prefer an assumption over an annotation-based condition, knows teardown still runs on abort, and avoids overusing assumptions to mask real failures.
Frames assumptions as part of keeping the test-suite signal honest (skip ≠ pass ≠ fail), and can advise team conventions on when skipping is acceptable vs when a test should be excluded or fixed.
## What this is about A **unit test** is a small method that runs a piece of your code and checks the result. **JUnit 5** (also called JUnit Jupiter) is the standard library for writing such tests in Java. Inside a test you use two families of checks that look similar but mean opposite things: **assertions** and **assumptions**. ## Assertions — verify the thing under test An **assertion** is a statement you claim must be true about your code's behavior. Methods live in `org.junit.jupiter.api.Assertions`: `assertTrue`, `assertEquals`, `assertThrows`, etc. If the claim is false, the assertion throws an `AssertionError` (specifically an `AssertionFailedError`), JUnit catches it, and the test is reported as **FAILED**. A failed test turns the build red — it signals a real defect. ```java assertEquals(4, calculator.add(2, 2)); // if not 4 → test FAILS ``` ## Assumptions — verify a precondition An **assumption** is a statement about the *environment or context* the test needs in order to be meaningful — not about the code's correctness. Methods live in `org.junit.jupiter.api.Assumptions`: `assumeTrue`, `assumeFalse`, `assumingThat`. If the assumption is **false**, JUnit throws a `TestAbortedException`, and the test is reported as **SKIPPED / ABORTED** — *not* failed. The build stays green. ```java assumeTrue("CI".equals(System.getenv("ENV"))); // false → test is SKIPPED // everything below here is skipped too ``` ## The key contrast | | Assertion | Assumption | |---|---|---| | Package | `Assertions` | `Assumptions` | | Checks | the behavior under test | a precondition / environment | | On false | **FAIL** (red build) | **SKIP/ABORT** (green build) | | Exception thrown | `AssertionFailedError` (an `AssertionError`) | `TestAbortedException` | | Meaning | 'the code is wrong' | 'this test does not apply here' | ## Why it matters Failing a test that simply can't run in the current environment (no database, wrong OS) is misleading — it hides real failures in noise. An assumption lets you say 'if the precondition is not met, just don't run me, and don't complain.' That keeps the failure signal honest: red means a genuine bug. ## Control flow note Both assertions and assumptions work by **throwing an exception** when they fail. That exception immediately unwinds the test method, so any code written after a failed assumption (or assertion) does **not** execute. The one exception is `assumingThat`, covered separately, which only gates a lambda rather than aborting the whole method.
- If an assumption fails, does the @AfterEach teardown still run?Yes. An aborted test still went through the lifecycle, so @AfterEach (and @AfterAll) callbacks still execute. The test is reported as aborted/skipped, but teardown is not bypassed.
- Which exception type does a failed assumeTrue throw, and which does a failed assertTrue throw?A failed assumeTrue throws org.opentest4j.TestAbortedException (caught as 'aborted'); a failed assertTrue throws org.opentest4j.AssertionFailedError, an AssertionError subclass (caught as 'failed').
An assertion is the exam itself — fail it and you flunk. An assumption is the eligibility check at the door: if you do not meet the prerequisite, you are simply turned away (not run), you do not get a failing grade.
saying these in an interview costs you the question
- Saying a failed assumption makes the test FAIL — it makes it SKIP/abort.
- Using an assumption to check the actual behavior under test (that should be an assertion).
- Thinking assertions and assumptions come from the same class — they are Assertions vs Assumptions.
- Claiming code after a failed assumption still runs — it does not (the method is aborted).