0Pricing
Testing Mastery: JUnit, Mockito & Integration Tests · Lektion

Testlebenszyklus und Reihenfolge

Steuern Sie die Ausführungsreihenfolge von Tests und verwalten Sie Testvorbereitung und -bereinigung mithilfe fortgeschrittener Lebenszyklus-Annotations.

Testlebenszyklus und Reihenfolge ist eine kostenlose Testing Mastery: JUnit, Mockito & Integration Tests-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Testing Mastery: JUnit, Mockito & Integration Tests-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Testing Mastery: JUnit, Mockito & Integration Tests-Kurs umfasst insgesamt 4 Lektionen.

Teile dieser Lektion wurden noch nicht übersetzt und werden auf Englisch angezeigt.

JUnit Test Lifecycle Intro

Welcome! In this lesson, we'll dive into advanced JUnit 5 features to control how your tests run. Understanding the test lifecycle is key to managing resources and ensuring proper test setup and cleanup.

The lifecycle defines the sequence of actions JUnit takes before and after your test methods and classes.

Class-Level Setup: @BeforeAll

Sometimes, you need to perform setup operations only once for all tests within a specific test class. The @BeforeAll annotation marks a method to run before any test method in that class.

By default, @BeforeAll methods must be static. We'll see how to change this soon!

import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class BeforeAllDemo {
    private static StringBuilder log = new StringBuilder();

    @BeforeAll
    static void setupOnce() {
        log.append("-> @BeforeAll: Setup done once.\n");
        System.out.println("Setup for all tests.");
    }

    @Test
    void testA() {
        log.append("  -> @Test: Running testA.\n");
        System.out.println("  Running testA.");
        assertTrue(true);
    }

    @Test
    void testB() {
        log.append("  -> @Test: Running testB.\n");
        System.out.println("  Running testB.");
        assertTrue(true);
    }
    // The log output would typically be verified in @AfterAll or debugger.
}

Class-Level Teardown: @AfterAll

Similarly, you might need to clean up resources once after all tests in a class have completed. The @AfterAll annotation marks a method to run after all test methods in the class.

Like @BeforeAll, it must be static by default.

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class AfterAllDemo {
    private static StringBuilder log = new StringBuilder();

    @BeforeAll
    static void setup() {
        log.append("-> @BeforeAll: Setup for AfterAllDemo.\n");
    }

    @Test
    void testOne() {
        log.append("  -> @Test: Running testOne.\n");
        assertTrue(true);
    }

    @Test
    void testTwo() {
        log.append("  -> @Test: Running testTwo.\n");
        assertTrue(true);
    }

    @AfterAll
    static void teardown() {
        log.append("-> @AfterAll: Teardown for AfterAllDemo.\n");
        System.out.println("--- Execution Log ---");
        System.out.println(log.toString()); // See the full order
        System.out.println("--- End Log ---");
    }
}

@TestInstance: PER_CLASS Lifecycle

By default, JUnit creates a new instance of your test class for each test method (Lifecycle.PER_METHOD). This ensures test isolation.

If you need @BeforeAll and @AfterAll methods to be non-static, or if you want to share state across all tests in a class, you can switch the test instance lifecycle to Lifecycle.PER_CLASS.

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import static org.junit.jupiter.api.Assertions.assertEquals;

@TestInstance(Lifecycle.PER_CLASS) // Allows non-static @BeforeAll/@AfterAll
public class PerClassLifecycleDemo {
    private int counter = 0; // Instance variable, shared across tests

    @BeforeAll // No longer needs to be static!
    void setupPerClass() {
        counter = 10; 
        System.out.println("-> @BeforeAll (PER_CLASS). Counter: " + counter);
    }

    @Test
    void testIncrementOne() {
        counter++;
        System.out.println("  -> @Test 1. Counter: " + counter);
        assertEquals(11, counter); // Shared state is modified
    }

    @Test
    void testIncrementTwo() {
        counter++;
        System.out.println("  -> @Test 2. Counter: " + counter);
        assertEquals(12, counter); // Counter continues from previous test
    }

    @AfterAll // No longer needs to be static!
    void teardownPerClass() {
        System.out.println("-> @AfterAll (PER_CLASS). Final Counter: " + counter);
    }
}

Test Ordering: When to Use

Ideally, JUnit tests should be independent and run correctly in any order. Relying on a specific order can make your tests fragile and harder to maintain.

However, there are specific scenarios where explicit ordering might be useful:

  • Testing a complex workflow with clear, sequential steps.
  • Optimizing performance by grouping fast tests or tests with shared expensive setup.
  • Working with legacy systems that demand a certain interaction sequence.

@TestMethodOrder Annotation

To define an execution order for test methods within a class, you use the @TestMethodOrder annotation at the class level. It takes a MethodOrderer implementation as an argument.

JUnit 5 provides several built-in strategies:

  • Alphanumeric.class: Orders by method name alphabetically.
  • OrderAnnotation.class: Uses the @Order annotation.
  • Random.class: Randomizes the order.
  • DisplayName.class: Orders by method display names.

Alphanumeric Method Order

Let's see MethodOrderer.Alphanumeric.class in action. JUnit will simply sort test methods based on their names in alphabetical order.

This is a simple way to get a predictable order if your method names naturally follow a sequence.

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.MethodOrderer.Alphanumeric;
import static org.junit.jupiter.api.Assertions.assertTrue;

@TestMethodOrder(Alphanumeric.class) // Tests run A, B, C
public class AlphanumericOrderDemo {

    @Test
    void testA_First() {
        System.out.println("-> Running testA_First");
        assertTrue(true);
    }

    @Test
    void testC_Third() {
        System.out.println("-> Running testC_Third");
        assertTrue(true);
    }

    @Test
    void testB_Second() {
        System.out.println("-> Running testB_Second");
        assertTrue(true);
    }
}

Custom Order with @Order

For fine-grained control, combine @TestMethodOrder(MethodOrderer.OrderAnnotation.class) with the @Order(value) annotation on individual test methods. Lower value numbers mean earlier execution.

This allows you to define a precise, custom order for your tests.

import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;
import org.junit.jupiter.api.MethodOrderer.OrderAnnotation;
import static org.junit.jupiter.api.Assertions.assertTrue;

@TestMethodOrder(OrderAnnotation.class) // Activate @Order annotation
public class CustomOrderDemo {

    @Test
    @Order(2) // This test runs second
    void processStepTwo() {
        System.out.println("-> Running processStepTwo");
        assertTrue(true);
    }

    @Test
    @Order(1) // This test runs first
    void initializeSystem() {
        System.out.println("-> Running initializeSystem");
        assertTrue(true);
    }

    @Test
    @Order(3) // This test runs third
    void finalizeReport() {
        System.out.println("-> Running finalizeReport");
        assertTrue(true);
    }
}

Ordering Best Practices

While powerful, explicit test ordering should be used with caution:

  • Prioritize Independence: Each test should ideally be able to run on its own.
  • Readability: Over-ordering can make tests harder to understand and maintain.
  • Maintenance Burden: Changes to the system might require re-evaluating and updating order values.

Only use ordering when there's a strong, justified reason, and prefer @Order for clear intent.

Lifecycle & Order Check

Consider the following JUnit 5 test class:

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

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class QuizTest {
    private int sharedValue = 0;

    @BeforeAll
    void setup() {
        sharedValue = 10;
        System.out.println("BeforeAll: sharedValue = " + sharedValue);
    }

    @Test
    @Order(2)
    void testB() {
        sharedValue += 2;
        System.out.println("  TestB: sharedValue = " + sharedValue);
        assertEquals(13, sharedValue);
    }

    @Test
    @Order(1)
    void testA() {
        sharedValue += 1;
        System.out.println("  TestA: sharedValue = " + sharedValue);
        assertEquals(11, sharedValue);
    }

    @AfterAll
    void teardown() {
        System.out.println("AfterAll: sharedValue = " + sharedValue);
    }
}

What will be the final value of sharedValue printed in the @AfterAll method?

Recap: Lifecycle & Ordering

In this lesson, you mastered advanced JUnit 5 features for controlling test execution:

  • Class-Level Lifecycle: @BeforeAll and @AfterAll for one-time setup/teardown.
  • Instance Lifecycle: @TestInstance(Lifecycle.PER_CLASS) to enable shared state and non-static class-level hooks.
  • Test Method Ordering: @TestMethodOrder (with strategies like Alphanumeric or OrderAnnotation) to define execution order.
  • Custom Order: @Order for precise control over method sequence.

Remember to use explicit ordering judiciously, prioritizing independent and robust tests!

Häufig gestellte Fragen

Ist die Lektion „Testlebenszyklus und Reihenfolge“ kostenlos?

Ja — der vollständige Text von „Testlebenszyklus und Reihenfolge“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Testing Mastery: JUnit, Mockito & Integration Tests-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Testing Mastery: JUnit, Mockito & Integration Tests-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Testlebenszyklus und Reihenfolge“?

Steuern Sie die Ausführungsreihenfolge von Tests und verwalten Sie Testvorbereitung und -bereinigung mithilfe fortgeschrittener Lebenszyklus-Annotations. Du übst Testing Mastery: JUnit, Mockito & Integration Tests mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um Testing Mastery: JUnit, Mockito & Integration Tests zu starten?

Keine Vorkenntnisse erforderlich. Testing Mastery: JUnit, Mockito & Integration Tests auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Testlebenszyklus und Reihenfolge“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser Testing Mastery: JUnit, Mockito & Integration Tests-Lektion Code schreiben und ausführen?

Ja. Jede Testing Mastery: JUnit, Mockito & Integration Tests-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Testlebenszyklus und Reihenfolge
  2. Parametrisierte und dynamische Tests
  3. Ausnahmetests und Timeouts
  4. Bedingte Tests und Annahmen
← Zurück zu Testing Mastery: JUnit, Mockito & Integration Tests