Testing i praksis: JUnit, Mockito og integrasjonstester · leksjon

Testlivssyklus og rekkefølge

Kontroller kjøringsrekkefølgen for tester, og håndter oppsett og nedbryting av tester ved hjelp av avanserte livssyklusannotasjoner.

Leksjon 1 av 411 trinn

Testlivssyklus og rekkefølge er en gratis leksjon i Testing i praksis: JUnit, Mockito og integrasjonstester på CoddyKit. Dette er leksjon 1 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Testing i praksis: JUnit, Mockito og integrasjonstester, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Testing i praksis: JUnit, Mockito og integrasjonstester inneholder totalt 4 leksjoner.

Introduksjon til JUnit-testlivssyklusen

Velkommen! I denne leksjonen skal du utforske avanserte JUnit 5-funksjoner for å styre hvordan testene kjøres. Det er viktig å forstå testlivssyklusen for å håndtere ressurser og sikre riktig oppsett og opprydding av tester.

Livssyklusen definerer rekkefølgen på handlingene JUnit utfører før og etter testmetodene og klassene dine.

Oppsett på klassenivå: @BeforeAll

Noen ganger trenger du å utføre oppsetthandlinger bare én gang for alle testene i en bestemt testklasse. Annotasjonen @BeforeAll markerer en metode som skal kjøre før alle testmetodene i klassen.

Som standard må @BeforeAll-metoder være static. Snart skal du se hvordan dette kan endres!

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.
}

Opprydding på klassenivå: @AfterAll

Tilsvarende kan det hende du må rydde opp i ressurser én gang etter at alle testene i en klasse er fullført. Annotasjonen @AfterAll markerer en metode som skal kjøre etter alle testmetodene i klassen.

I likhet med @BeforeAll må den som standard være static.

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-livssyklus

Som standard oppretter JUnit en ny instans av testklassen for hver testmetode (Lifecycle.PER_METHOD). Dette sikrer at testene er isolerte.

Hvis du trenger at @BeforeAll- og @AfterAll-metoder skal være ikke-statiske, eller hvis du vil dele tilstand mellom alle testene i en klasse, kan du endre testinstansens livssyklus til 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);
    }
}

Når bør testrekkefølge brukes?

Ideelt sett bør JUnit-tester være uavhengige og kjøre riktig i hvilken som helst rekkefølge. Hvis du er avhengig av en bestemt rekkefølge, kan testene bli sårbare og vanskeligere å vedlikeholde.

Det finnes likevel enkelte situasjoner der en eksplisitt rekkefølge kan være nyttig:

  • Testing av en kompleks arbeidsflyt med tydelige, sekvensielle trinn.
  • Optimalisering av ytelsen ved å gruppere raske tester eller tester med felles, kostbart oppsett.
  • Arbeid med eldre systemer som krever en bestemt rekkefølge på samhandlingene.

@TestMethodOrder-annotasjonen

For å definere en utførelsesrekkefølge for testmetoder i en klasse bruker du annotasjonen @TestMethodOrder på klassenivå. Den tar en implementasjon av MethodOrderer som argument.

JUnit 5 har flere innebygde strategier:

  • Alphanumeric.class: Sorterer alfabetisk etter metodenavn.
  • OrderAnnotation.class: Bruker @Order-annotasjonen.
  • Random.class: Gjør rekkefølgen tilfeldig.
  • DisplayName.class: Sorterer etter visningsnavnene til metodene.

Alfanumerisk metoderekkefølge

La oss se MethodOrderer.Alphanumeric.class i praksis. JUnit sorterer ganske enkelt testmetodene etter navn i alfabetisk rekkefølge.

Dette er en enkel måte å få en forutsigbar rekkefølge på hvis metodenavnene dine naturlig følger en sekvens.

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);
    }
}

Egendefinert rekkefølge med @Order

For detaljert kontroll kombinerer du @TestMethodOrder(MethodOrderer.OrderAnnotation.class) med annotasjonen @Order(value) på individuelle testmetoder. Lavere value-verdier betyr tidligere kjøring.

Dette lar deg definere en presis, egendefinert rekkefølge for testene dine.

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);
    }
}

Beste praksis for rekkefølge

Selv om eksplisitt testrekkefølge er kraftig, bør den brukes med varsomhet:

  • Prioriter uavhengighet: Hver test bør ideelt sett kunne kjøres alene.
  • Lesbarhet: For mye styring av rekkefølgen kan gjøre testene vanskeligere å forstå og vedlikeholde.
  • Vedlikeholdsbyrde: Endringer i systemet kan kreve at du vurderer og oppdaterer rekkefølgeverdiene på nytt.

Bruk bare rekkefølgestyring når det finnes en sterk og velbegrunnet grunn, og foretrekk @Order for å gjøre hensikten tydelig.

Kontroll av livssyklus og rekkefølge

Se på følgende JUnit 5-testklasse:

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);
    }
}

Hva blir den endelige verdien av sharedValue som skrives ut i @AfterAll-metoden?

Oppsummering: Livssyklus og rekkefølge

I denne leksjonen har du lært avanserte JUnit 5-funksjoner for å styre testkjøringen:

  • Livssyklus på klassenivå: @BeforeAll og @AfterAll for oppsett og opprydding som bare utføres én gang.
  • Instanslivssyklus: @TestInstance(Lifecycle.PER_CLASS) for å aktivere delt tilstand og ikke-statiske koblinger på klassenivå.
  • Rekkefølge for testmetoder: @TestMethodOrder (med strategier som Alphanumeric eller OrderAnnotation) for å definere utførelsesrekkefølgen.
  • Egendefinert rekkefølge: @Order for presis kontroll over metodenes rekkefølge.

Husk å bruke eksplisitt rekkefølge med omtanke, og prioriter uavhengige og robuste tester!

Gratis å komme i gang

Lær deg Testing i praksis: JUnit, Mockito og integrasjonstester med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
12
Leksjoner
48

Ofte stilte spørsmål

Er leksjonen «Testlivssyklus og rekkefølge» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Testing i praksis: JUnit, Mockito og integrasjonstester, inkludert «Testlivssyklus og rekkefølge», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Testing i praksis: JUnit, Mockito og integrasjonstester inneholder totalt 4 leksjoner.

Hva lærer jeg i «Testlivssyklus og rekkefølge»?

Kontroller kjøringsrekkefølgen for tester, og håndter oppsett og nedbryting av tester ved hjelp av avanserte livssyklusannotasjoner. Du øver på Testing i praksis: JUnit, Mockito og integrasjonstester med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med Testing i praksis: JUnit, Mockito og integrasjonstester?

Ingen tidligere erfaring er nødvendig. Testing i praksis: JUnit, Mockito og integrasjonstester på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 1 av 4.

Hvor lang tid tar leksjonen «Testlivssyklus og rekkefølge»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne Testing i praksis: JUnit, Mockito og integrasjonstester-leksjonen?

Ja. Alle Testing i praksis: JUnit, Mockito og integrasjonstester-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. Testlivssyklus og rekkefølge
  2. Parametriserte og dynamiske tester
  3. Testing av unntak og tidsavbrudd
  4. Betingede tester og antakelser
← Tilbake til Testing i praksis: JUnit, Mockito og integrasjonstester