How do you make JUnit 5 execute the test methods of a class in an order you control, and what exactly does the number you supply on each method mean?
answer
- @TestMethodOrder on class + @Order on methods
- Lower value first; negatives legal
- No @Order = Integer.MAX_VALUE / 2, not 0
- Stable sort — equal values keep prior order
- Leave gaps: 10, 20, 30
basics
~20 sPut @TestMethodOrder(MethodOrderer.OrderAnnotation.class) on the class and @Order(n) on the methods. Lower n runs first; methods without @Order get Integer.MAX_VALUE / 2, so they land between negative and large values. Ties keep their prior relative order.
solid answer
~50 sTwo annotations. `@TestMethodOrder(MethodOrderer.OrderAnnotation.class)` on the class selects the orderer; `@Order(int)` on each test method supplies the sort key. **Lower values run first**, and the value is a plain `int`, so negatives are legal. The part candidates miss: `@Order` is optional per method, and any method without it gets `Order.DEFAULT`, which is `Integer.MAX_VALUE / 2`. So an un-annotated method runs *after* everything numbered 1, 2, 3 but *before* anything numbered `Integer.MAX_VALUE`. Do not assume un-annotated means "first". The sort is stable, so methods sharing a value keep the engine's default (non-obvious) relative order — equal `@Order` values do not give you a defined order between them. A common convention is to leave gaps (10, 20, 30) so you can insert a step later without renumbering. `@TestMethodOrder` is also inheritable by subclasses, and the same `@Order` annotation is reused elsewhere in JUnit — for ordering registered extensions and, with `ClassOrderer.OrderAnnotation`, for ordering test classes.
code
java · 15 lines@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class CheckoutFlowTest {
@Order(10)
@Test
void createsCart() { }
@Order(20)
@Test
void addsItem() { }
// no @Order -> Order.DEFAULT (Integer.MAX_VALUE / 2) -> runs after 10 and 20
@Test
void showsEmptyBadge() { }
}go deeper
Name both annotations and the direction (lower first); that alone answers the screening version of this question.
Add the Order.DEFAULT = Integer.MAX_VALUE / 2 rule, stable-sort tie behaviour, and the gap-numbering convention.
Distinguish ordering-as-documentation from ordering-as-dependency and state what the second one costs: single-test runs, rerun-failed, cascading failures, parallelism.
Treat it as a policy question — where ordered scenario classes are allowed in the suite, how they are named and contained, and why the rest of the suite must stay order-free to remain shardable.
## The mechanism JUnit Jupiter exposes ordering through the `MethodOrderer` SPI. You select an implementation with a class-level annotation: ```java @TestMethodOrder(MethodOrderer.OrderAnnotation.class) class CheckoutFlowTest { ... } ``` `MethodOrderer.OrderAnnotation` reads the `@Order` annotation on each test method and sorts ascending. Everything else about the class is unchanged: `@BeforeEach`/`@AfterEach` still run around every method, a fresh test-class instance is still created per method under the default lifecycle, and assertions behave the same. Ordering only decides the sequence. ## The semantics of the number `@Order` takes a single `int` value. The contract is: - **Lower first.** `@Order(1)` runs before `@Order(2)`. There is no `priority`-style inversion. - **Negative values are legal.** `@Order(-100)` is a perfectly good "run this before everything". - **Missing annotation is not zero.** `Order.DEFAULT` is `Integer.MAX_VALUE / 2`. A method with no `@Order` therefore sorts *after* every small positive value and *before* very large ones. This trips people who annotate three of five methods and expect the other two to run first — they run last (relative to 1..n). - **Ties are unresolved.** The sort is stable, so two methods with the same value keep whatever relative order the engine had before sorting — which is the default non-obvious order. Duplicated `@Order` values are effectively "I don't care between these two"; if you do care, give them distinct values. Because the key is a raw `int` and not a dependency graph, JUnit never says "B must run after A"; it says "sort by key". There is no `@DependsOn` in JUnit 5 (that is a TestNG feature), and no automatic skipping of later steps when an earlier one fails — a failure at step 1 does not prevent step 2 from running, it just usually makes it fail too. ## Idiomatic usage Leave gaps: `@Order(10)`, `@Order(20)`, `@Order(30)`. Inserting a step later then costs one annotation instead of renumbering the file. Some teams instead define named constants (`static final int CREATE = 10;`) so the intent reads in the annotation. Keep ordered classes small and obviously scenario-shaped, and name them accordingly (`CheckoutScenarioTest`). Mixing three ordered "steps" with fifteen independent unit tests in one class is the worst of both worlds: readers cannot tell which methods are load-bearing in sequence. ## Where else @Order shows up The same `org.junit.jupiter.api.Order` annotation is reused across Jupiter: - With `@TestClassOrder(ClassOrderer.OrderAnnotation.class)`, it orders `@Nested` test classes. - On declaratively registered extensions (`@RegisterExtension` fields), it orders extension registration, which in turn orders callback execution. So seeing `@Order` in a codebase does not by itself mean method ordering; check what orderer is in play. ## Inheritance and scope `@TestMethodOrder` is `@Inherited`, so a base test class can impose an ordering policy on subclasses. It applies to the methods of the class it is discovered on; a `@Nested` inner class is its own container and needs its own ordering configuration if you want one there. ## What ordering costs you Once a class is ordered *and the tests actually depend on that order*, you have accepted: - **No meaningful single-test run.** Running step 3 alone from the IDE will fail. - **No meaningful rerun-failed.** CI reruns of just the failed method reproduce nothing. - **Cascading failures.** One broken step turns into N red tests, and the report no longer tells you how many things are actually broken. - **Constraints under parallel execution.** Ordering describes the order tests are *started*; if the engine runs methods concurrently, "after" is not guaranteed unless the class is pinned to a single thread. That is why the honest interview answer distinguishes two cases. *Ordering as documentation* — you order tests so the report reads like a story, but every test would still pass alone — is cheap and harmless. *Ordering as a dependency* — step 2 cannot pass without step 1 — is a real design decision with the costs above, justified only when re-establishing the fixture per test is genuinely prohibitive (a long UI or migration scenario, an expensive external environment). If you reach for `@Order` to fix an intermittently failing suite, you are hiding a shared-state bug, not fixing it. ## Quick reference ```java @TestMethodOrder(MethodOrderer.OrderAnnotation.class) // pick the orderer class T { @Order(-1) @Test void first() {} // negatives allowed @Order(10) @Test void second() {} @Test void third() {} // Order.DEFAULT = MAX_VALUE/2 -> last here } ```
- Two methods in an ordered class carry @Order(5). Which one runs first?Unspecified in any useful sense. The orderer sorts stably, so the two keep whatever relative order the engine produced before sorting — the default non-obvious order — which can differ between JUnit versions. If the sequence between them matters, give them distinct values.
- Step 1 of an ordered class fails. Does JUnit skip steps 2 and 3?No. JUnit 5 has no inter-test dependency model, so every remaining method still executes and typically fails too, producing a cascade of red tests from one root cause. If you need short-circuiting you have to build it yourself — for example an assumption in later steps that checks a flag set by the earlier one, which converts the cascade into skips.
saying these in an interview costs you the question
- Thinking a method without @Order runs first (it gets Integer.MAX_VALUE / 2 and runs late).
- Assuming higher @Order values run first.
- Believing @Order alone works without @TestMethodOrder(MethodOrderer.OrderAnnotation.class) on the class.
- Expecting JUnit to skip later steps when an earlier ordered step fails, TestNG-style @DependsOn behaviour.
- Reaching for @Order to stabilise a flaky suite instead of removing the shared mutable state.