Testen in Java: Unit-, Integrations- und E2E-Tests – vollständiger Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Testen in Java: Von Modultests bis zu End-to-End-Tests



Codequalität ist einer der wichtigsten Indikatoren für die Professionalität eines Entwicklers. In der Java-Welt ist Testen längst nicht nur eine gute Praxis, sondern ein Industriestandard. Ohne zuverlässige Tests ist es schwierig, große Projekte zu warten, neue Funktionen zu implementieren und Code sicher zu refaktorisieren. In diesem Artikel betrachten wir drei wichtige Testebenen: unit (Modultests), integration (Integrationstests) und e2e (End-to-End-Tests). Sie erfahren, wie sie sich unterscheiden, wie man sie in Java richtig schreibt und welche Werkzeuge man verwendet.



Die Testpyramide und warum sie wichtig ist

Bevor wir ins Detail gehen, sollten wir uns an das Konzept der Testpyramide (Mike Cohn) erinnern. Sie veranschaulicht das ideale Verhältnis von Tests auf verschiedenen Ebenen:

  • Unit-Tests (Basis der Pyramide) – am schnellsten, günstigsten und zahlreichsten. Sie sollten etwa 70 % ausmachen.
  • Integrationstests (Mitte) – prüfen das Zusammenspiel von Komponenten. Sie machen etwa 20 % aus.
  • E2E-Tests (Spitze) – am langsamsten und teuersten, aber entscheidend für die Überprüfung von Benutzerszenarien. Sie machen etwa 10 % aus.

Die Einhaltung dieses Verhältnisses ermöglicht maximale Sicherheit im Code bei minimalem Zeitaufwand für die Testausführung.



1. Unit-Testing in Java

Unit-Tests prüfen isoliert eine einzelne „Einheit" des Codes – in der Regel eine Methode oder Klasse. Ihr Hauptziel ist es, sicherzustellen, dass die Logik der Methode unabhängig von externen Abhängigkeiten (Datenbanken, APIs, Dateisystem) korrekt funktioniert. Zur Isolierung werden Mock-Objekte verwendet.



Wichtige Werkzeuge

  • JUnit 5 – das Standard-Framework zum Schreiben von Tests.
  • Mockito – eine Bibliothek zum Erstellen von Mock-Objekten und Überprüfen von Interaktionen.
  • AssertJ – eine Bibliothek für fließende Assertions (erhöht die Lesbarkeit).


Beispiel eines Unit-Tests mit JUnit 5 und Mockito

Angenommen, wir haben einen Service UserService, der von UserRepository abhängt:

public class UserService {    private final UserRepository repository;        public UserService(UserRepository repository) {        this.repository = repository;    }        public User findById(Long id) {        return repository.findById(id)                .orElseThrow(() -> new UserNotFoundException(\"User not found\"));    }}

Test für diese Methode:

import org.junit.jupiter.api.Test;import org.junit.jupiter.api.extension.ExtendWith;import org.mockito.InjectMocks;import org.mockito.Mock;import org.mockito.junit.jupiter.MockitoExtension;import java.util.Optional;import static org.junit.jupiter.api.Assertions.*;import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)class UserServiceTest {

@Mock private UserRepository repository;

@InjectMocks private UserService userService;

@Test void testFindById_UserExists() { // Given Long userId = 1L; User expectedUser = new User(userId, \"Alice\"); when(repository.findById(userId)).thenReturn(Optional.of(expectedUser));

// When User actualUser = userService.findById(userId);

// Then assertNotNull(actualUser); assertEquals(\"Alice\", actualUser.getName()); verify(repository).findById(userId); }

@Test void testFindById_UserNotFound() { // Given Long userId = 99L; when(repository.findById(userId)).thenReturn(Optional.empty());

// When & Then assertThrows(UserNotFoundException.class, () -> userService.findById(userId)); }}

Best Practices:

  • Testen Sie ei

Blogs

Buchempfehlungen