Komplett guide til Spring Boot 4 · leksjon

Enhetstesting med JUnit og Mockito

Skriv effektive enhetstester for komponentene i tjenestelaget ved hjelp av JUnit 5 og Mockito for mocking av avhengigheter.

Leksjon 1 av 411 trinn

Enhetstesting med JUnit og Mockito er en gratis leksjon i Komplett guide til Spring Boot 4 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 Komplett guide til Spring Boot 4, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Komplett guide til Spring Boot 4 inneholder totalt 4 leksjoner.

Velkommen til enhetstesting!

I denne leksjonen skal De lære å skrive effektive enhetstester for Spring Boot-applikasjoner, med særlig fokus på tjenestelaget.

Enhetstester er avgjørende for å sikre at koden fungerer som forventet og for å oppdage feil tidlig i utviklingen. Vi skal bruke JUnit 5 og Mockito.

Hva er enhetstesting?

Enhetstesting betyr å teste den minste mulige delen av koden, kalt en «enhet», isolert. I Java er en enhet vanligvis én enkelt metode eller klasse.

  • Isolasjon: Testene kjøres uavhengig av hverandre, uten eksterne avhengigheter.
  • Hastighet: De kjøres svært raskt, slik at de kan kjøres ofte.
  • Tidlig oppdagelse: Oppdag feil før de utvikler seg til større problemer.

Introduksjon til JUnit 5

JUnit 5 er det mest populære testrammeverket for Java. Det tilbyr annotasjoner og påstander som hjelper Dem med å skrive strukturerte og lettleste tester.

La oss se på den grunnleggende strukturen til en testklasse. Legg merke til at @Test-annotasjonen markerer en metode som et testtilfelle.

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

class SimpleCalculator {
  int add(int a, int b) {
    return a + b;
  }
}

// This is a JUnit 5 test class
class SimpleCalculatorTest {

  @Test
  void testAddition() {
    SimpleCalculator calc = new SimpleCalculator();
    int result = calc.add(2, 3);
    // An 'assertion' checks if the result is correct
    assertEquals(5, result, "2 + 3 should be 5");
    System.out.println("Addition test passed!");
  }

  public static void main(String[] args) {
    // In a real project, JUnit runs tests automatically.
    // Here, we simulate a call for demonstration.
    System.out.println("--- Simulating JUnit Test ---");
    new SimpleCalculatorTest().testAddition();
    System.out.println("--- Simulation Complete ---");
  }
}

Fokus på tjenestelaget

I Spring Boot inneholder servicelaget vanligvis applikasjonens forretningslogikk. Det koordinerer operasjoner og er ofte avhengig av datarepoer.

Enhetstesting av tjenester er ideelt fordi de:

  • Inneholder kjernelogikken.
  • Vanligvis er vanlige Java-klasser.
  • Enkelt kan isoleres fra eksterne systemer (for eksempel databaser).

Utfordringen: Avhengigheter

Tjenester er ofte avhengige av andre komponenter, for eksempel et UserRepository for å hente brukerdata. Når vi enhetstester en tjeneste, ønsker vi ikke å koble oss til en ekte database.

Det er her mocking kommer inn! Vi må simulere disse avhengighetene for å sikre at testen faktisk er en «enhetstest» (isolert).

Vi introduserer Mockito for mocking

Mockito er et populært mocking-rammeverk for Java. Det lar deg opprette «mock»-objekter som simulerer oppførselen til ekte objekter.

I stedet for at et ekte UserRepository kommuniserer med en database, forteller vi et mock-repository opprettet av Mockito nøyaktig hva det skal returnere når bestemte metoder kalles.

Konfigurere mocks med annotasjoner

Mockito tilbyr praktiske annotasjoner som forenkler oppretting og injisering av mocks:

  • @Mock: Oppretter et mock-objekt for den angitte typen.
  • @InjectMocks: Oppretter en instans av klassen som testes og injiserer @Mock-objektene i den.
import org.mockito.Mock;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;

// Simple dependent class (e.g., a repository)
class DataRepository {
  String findDataById(String id) {
    throw new UnsupportedOperationException("Not implemented for real use!");
  }
}

// Our service class under test
class MyService {
  private final DataRepository repository;

  MyService(DataRepository repository) {
    this.repository = repository;
  }

  String processData(String id) {
    return "Processed: " + repository.findDataById(id);
  }
}

class MyServiceTestSetup {

  @Mock
  DataRepository mockRepository; // Mock of DataRepository

  @InjectMocks
  MyService myService; // Service where mocks are injected

  MyServiceTestSetup() {
    // This initializes the mocks
    MockitoAnnotations.openMocks(this);
    System.out.println("Mocks initialized for MyServiceTest!");
    System.out.println("mockRepository is a Mockito mock: " + (mockRepository != null));
    System.out.println("myService has mock injected: " + (myService != null));
  }

  public static void main(String[] args) {
    System.out.println("--- Setting Up Mocks Demo ---");
    new MyServiceTestSetup();
    System.out.println("--- Demo Complete ---");
  }
}

Definere mock-oppførsel: when().thenReturn()

Når du har en mock, må du fortelle den hvordan den skal oppføre seg. Bruk Mockito.when().thenReturn() for å definere hva en mock-metode skal returnere for bestemte inndata.

Dette lar tjenesten kjøre logikken sin med testdataene fra mocken, uten behov for en ekte database eller ekstern tjeneste.

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.mockito.Mock;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.when;

// Re-using classes from previous example
class DataRepository {
  String findDataById(String id) {
    return "Real Data for " + id;
  }
}

class MyService {
  private final DataRepository repository;
  MyService(DataRepository repository) {
    this.repository = repository;
  }
  String processData(String id) {
    return "Processed: " + repository.findDataById(id);
  }
}

class MyServiceTestBehavior {

  @Mock
  DataRepository mockRepository;

  @InjectMocks
  MyService myService;

  MyServiceTestBehavior() {
    MockitoAnnotations.openMocks(this);
  }

  @Test
  void testProcessDataWithMock() {
    // 1. Define mock behavior: when findDataById("123") is called,
    //    return "Mocked Data".
    when(mockRepository.findDataById("123")).thenReturn("Mocked Data");

    // 2. Call the service method
    String result = myService.processData("123");

    // 3. Assert the result
    assertEquals("Processed: Mocked Data", result);
    System.out.println("Test passed! Result: " + result);
  }

  public static void main(String[] args) {
    System.out.println("--- Mock Behavior Demo ---");
    MyServiceTestBehavior test = new MyServiceTestBehavior();
    test.testProcessDataWithMock();
    System.out.println("--- Demo Complete ---");
  }
}

Kontrollere interaksjoner med verify()

Noen ganger er du ikke bare opptatt av returverdien, men også av om en bestemt metode på en mock ble kalt, og med hvilke argumenter.

Mockito-metoden verify() lar deg kontrollere at interaksjonene med mock-objektene skjedde som forventet. Dette er nyttig for å kontrollere bivirkninger.

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.mockito.Mock;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.times;

// Re-using classes from previous example
class DataRepository {
  String findDataById(String id) {
    return "Real Data for " + id;
  }
}

class MyService {
  private final DataRepository repository;
  MyService(DataRepository repository) {
    this.repository = repository;
  }
  String processData(String id) {
    return "Processed: " + repository.findDataById(id);
  }
  void saveData(String id, String data) {
    // Imagine this saves to DB via repository
    repository.findDataById(id); // Example interaction
    System.out.println("Saving data via mock...");
  }
}

class MyServiceTestVerification {

  @Mock
  DataRepository mockRepository;

  @InjectMocks
  MyService myService;

  MyServiceTestVerification() {
    MockitoAnnotations.openMocks(this);
  }

  @Test
  void testProcessDataAndVerify() {
    // Define mock behavior
    when(mockRepository.findDataById("456")).thenReturn("Verify Data");

    // Call the service method
    String result = myService.processData("456");

    // Assert the result
    assertEquals("Processed: Verify Data", result);

    // Verify that findDataById was called exactly once with "456"
    verify(mockRepository, times(1)).findDataById("456");
    System.out.println("Test passed! Method interaction verified.");
  }

  public static void main(String[] args) {
    System.out.println("--- Mock Verification Demo ---");
    MyServiceTestVerification test = new MyServiceTestVerification();
    test.testProcessDataAndVerify();
    System.out.println("--- Demo Complete ---");
  }
}

Rask sjekk: Mockitos rolle

Når du enhetstester en Spring-tjeneste som er avhengig av et repository, hva er Mockitos viktigste rolle?

Oppsummering: Bli god på enhetstesting

Gratulerer! Du har tatt de første stegene mot effektiv enhetstesting med Spring Boot.

  • Enhetstester verifiserer små kodenheter isolert.
  • JUnit 5 er testingsrammeverket vårt, og bruker @Test.
  • Vi fokuserer på servicelaget for forretningslogikk.
  • Mockito hjelper oss med å opprette mock-objekter for avhengigheter.
  • Bruk @Mock og @InjectMocks for å konfigurere tester.
  • Definer mock-oppførsel med when().thenReturn().
  • Kontroller interaksjoner med verify().

Fortsett å øve, så blir koden din mer robust enn noen gang!

Gratis å komme i gang

Lær deg Java 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
21
Leksjoner
84

Ofte stilte spørsmål

Er leksjonen «Enhetstesting med JUnit og Mockito» gratis?

Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Komplett guide til Spring Boot 4, inkludert «Enhetstesting med JUnit og Mockito», 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 Komplett guide til Spring Boot 4 inneholder totalt 4 leksjoner.

Hva lærer jeg i «Enhetstesting med JUnit og Mockito»?

Skriv effektive enhetstester for komponentene i tjenestelaget ved hjelp av JUnit 5 og Mockito for mocking av avhengigheter. Du øver på Komplett guide til Spring Boot 4 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 Komplett guide til Spring Boot 4?

Ingen tidligere erfaring er nødvendig. Komplett guide til Spring Boot 4 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 «Enhetstesting med JUnit og Mockito»?

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 Komplett guide til Spring Boot 4-leksjonen?

Ja. Alle Komplett guide til Spring Boot 4-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. Enhetstesting med JUnit og Mockito
  2. Integrasjonstesting med Spring Boot
  3. Slicetesting og TestContainers
  4. Test webkontrollere med MockMvc
← Tilbake til Komplett guide til Spring Boot 4