skip to content

Test Ordering

Making execution order deterministic when you must — and why needing to is usually a design smell. Interviewers probe the MethodOrderer options and the default ordering reality.

on this pageshow

questions

5

In JUnit 5 (Jupiter), what order are the @Test methods inside one test class executed in when you do not configure anything, and what does that imply for how those tests must be written?

level: juniorimportance: must knowfreq 58%

answer

  1. No orderer by default
  2. Deterministic, intentionally non-obvious
  3. Not source order, not alphabetical
  4. May change between JUnit versions
  5. static mutable field = order-dependency smell

basics

~20 s

Jupiter applies no orderer by default, so methods run in a deterministic but intentionally non-obvious order — not source order, not alphabetical — and it may change between versions. Each test must therefore pass independently, in any order.

solid answer

~50 s

JUnit Jupiter deliberately does **not** run test methods in source order or alphabetical order. With no `@TestMethodOrder` present, the engine sorts methods with an internal, hash-based algorithm: the result is deterministic for a given JUnit version and class, but intentionally unpredictable to a reader, and the JUnit team reserves the right to change it. JUnit 4 behaved similarly (`MethodSorters.DEFAULT`) unless you added `@FixMethodOrder`. The reason is partly technical — reflection gives no reliable declaration order — and mostly pedagogical: tests that depend on each other break under tag filtering, rerun-failed, running a single test from the IDE, and parallel execution. So each method should build the state it needs (fresh fixtures, `@BeforeEach`) and assert only on that. If you genuinely need an order — a long scenario, one expensive fixture — you opt in explicitly with `@TestMethodOrder(MethodOrderer.OrderAnnotation.class)` plus `@Order(n)`, and you accept that the class is now a sequence rather than a set of independent tests.

code

java · 15 lines
java
class UserServiceTest {

    private static Long createdId;

    @Test
    void createsUser() {
        createdId = service.create("ann");
        assertNotNull(createdId);
    }

    @Test
    void findsUser() {
        assertNotNull(service.find(createdId)); // NPE when this runs first
    }
}

go deeper

for a junior

Recall the rule: no guaranteed order, so never let one test depend on another; put shared setup in @BeforeEach.

for a middle

Explain why — reflection gives no declaration order, and the design forces independence — and name the opt-in escape hatch (@TestMethodOrder plus @Order).

for a senior

Talk about how order dependencies actually surface (single-test runs, filters, rerun-failed, parallelism) and how you would hunt them down with random ordering and per-test data isolation.

for a principal

Frame it as a suite-health policy: independence is what makes sharding, parallelism and rerun-failed possible; ordered classes are a deliberate, contained exception with a stated cost.

## The rule In JUnit Jupiter (JUnit 5), the test methods of a class are executed in a **deterministic but intentionally non-obvious order** unless you explicitly configure a `MethodOrderer`. "Deterministic" means: same class, same JUnit version, same JVM → same order every run. "Non-obvious" means: it is *not* the order the methods appear in the source file, and it is *not* alphabetical. Internally the engine sorts by a hash derived from the method name and parameter types, so the sequence looks arbitrary to a human reader. ## Why not source order? Two reasons. **Technical.** The JVM gives no guarantee about the order `Class#getDeclaredMethods()` returns members. The Javadoc explicitly says the elements are in no particular order. HotSpot happens to return something stable per compilation, but it is not contractual and has historically varied. A framework that promised source order would be promising something the platform does not provide. **Deliberate design.** Even if source order were available, JUnit does not want you leaning on it. A test suite is a *set* of independent facts, not a script. Once test B only passes because test A ran first, several everyday operations break: - Running one test alone from the IDE (`Run 'shouldChargeCard'`) fails, because the setup lived in a different method. - Tag or name filters that select a subset silently change the outcome. - "Rerun failed tests" reruns only some of the chain. - Parallel execution scrambles the assumption entirely. - Deleting or renaming an unrelated test changes the hash order and breaks something far away. The non-obvious ordering exists so those defects surface *early*, in development, rather than at 2 a.m. in CI. ## What "deterministic" does and does not promise It promises reproducibility within one setup, which is useful when you are debugging: a failure caused by ordering will keep reproducing locally. It promises **nothing** across JUnit versions. The Jupiter documentation states the algorithm may change, so upgrading a patch version can legitimately reshuffle your class. Treat the default order as an implementation detail you observe, never as a contract you code against. ## How this bites in practice The classic shape is a mutable field on the test class: ```java class UserServiceTest { private static Long createdId; // shared across methods @Test void createsUser() { createdId = service.create("ann"); } @Test void findsUser() { assertNotNull(service.find(createdId)); } // NPE if run first } ``` A second shape is shared external state: test A inserts rows, test B counts them; test A registers a mock's behaviour on a static singleton, test B consumes it. Note also that Jupiter creates a **new instance of the test class per test method** by default, so instance fields are reset — which is exactly why order-dependent code usually degenerates into `static` fields or external state. Both make the dependency easy to spot in review: a `static` mutable field in a test class is a smell. ## Writing order-independent tests - Put shared, cheap setup in `@BeforeEach` so each method starts from the same known state. - Put expensive one-time setup in `@BeforeAll` (a container/server/schema) but keep it **read-only or reset per test**; a shared resource is fine, shared *mutation* is not. - Roll back or truncate data between tests (transactional test support, `@AfterEach` cleanup, throwaway containers). - Give each test its own unique data (random e-mails, generated keys) so two tests cannot collide. - Prove independence by shuffling: configure `MethodOrderer.Random` temporarily, or run single tests in isolation. If a test only passes in a suite, it is not a test yet. ## When you legitimately want an order There are real cases: an end-to-end scenario where each step is expensive and re-doing it per test would triple the suite time; a migration or workflow test where the steps *are* the specification. In those cases opt in explicitly — `@TestMethodOrder(MethodOrderer.OrderAnnotation.class)` with `@Order(n)` — and keep the ordered class small and clearly named, because you have traded away rerun-single-test, filtering, and parallelism inside it. Making the intent explicit also tells the next reader that the sequence is deliberate rather than accidental. ## Contrast with JUnit 4 JUnit 4 had the same philosophy: `MethodSorters.DEFAULT` is a deterministic hash order, `MethodSorters.NAME_ASCENDING` and `JVM` were opt-in via `@FixMethodOrder`. Jupiter replaced that with the pluggable `MethodOrderer` SPI, which is strictly more capable (built-in orderers, a global default, custom implementations), but the default answer to "what order do my tests run in?" is unchanged: one you should not depend on.

  • How would you prove that a test class really is order-independent?
    Run it with a randomising orderer — set `@TestMethodOrder(MethodOrderer.Random.class)` or the `junit.jupiter.testmethod.order.default` configuration parameter — several times, and separately run each test alone (IDE single-test run or a name filter). If a test only passes inside the suite, it depends on a neighbour. Some teams keep random ordering on permanently in CI so the dependency shows up as a flaky failure with a logged seed you can replay.
  • Jupiter creates a new test-class instance per test method. Doesn't that already prevent order dependencies?
    It removes one channel: instance fields are reset for every test method, so state cannot leak through them. It does nothing about `static` fields, the database, files, system properties, a shared container, or a mocked singleton. Those are where real order dependencies live, and they survive the fresh instance.

Think of a test class as a bag of marbles, not a chain of dominoes. JUnit deliberately shakes the bag so you notice if you have secretly glued the marbles together.

saying these in an interview costs you the question

  • Saying tests run top-to-bottom in source order.
  • Saying the default order is alphabetical (that is JUnit 4's opt-in NAME_ASCENDING, not any default).
  • Claiming the order is random each run — it is deterministic, just not obvious.
  • Treating the observed default order as a stable contract you can rely on after a JUnit upgrade.
  • Fixing an order-dependent suite by adding @Order instead of removing the shared mutable state.

context

open as a page

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?

level: middleimportance: must knowfreq 52%

basics

~20 s

Put @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.

open as a page

Besides sorting by an explicit priority number, what other built-in strategies does JUnit 5 provide for sorting test methods, and how would you apply one across an entire codebase without editing every test class?

level: middleimportance: should knowfreq 34%

basics

~10 s

JUnit 5 ships MethodOrderer.OrderAnnotation, MethodName, DisplayName and Random. Apply one globally with the junit.jupiter.testmethod.order.default configuration parameter (for example in junit-platform.properties) instead of annotating each class. You can also implement MethodOrderer yourself.

open as a page

How do you control the order in which JUnit 5 runs whole test classes, including inner classes marked @Nested, and what are the limits of that control?

level: seniorimportance: should knowfreq 26%

basics

~10 s

Use @TestClassOrder(ClassOrderer.OrderAnnotation.class) on an enclosing class to order its @Nested classes, with @Order on each nested class. Top-level classes are ordered only via the junit.jupiter.testclass.order.default configuration parameter. Built-in orderers: ClassName, DisplayName, OrderAnnotation, Random.

open as a page

A JUnit 5 test class relies on a fixed execution order of its methods, and the team now wants to enable Jupiter's parallel execution for the whole suite. What actually breaks, and how do you decide between preserving the ordering and removing the dependency between those tests?

level: principalimportance: should knowfreq 22%

basics

~20 s

Under parallel execution an orderer fixes the order tests are started, not that one finishes before the next begins. Pin ordered classes to a single thread (@Execution(SAME_THREAD)) or guard shared state with @ResourceLock — then decide whether the sequence is genuinely worth losing parallelism and single-test reruns.

open as a page