Glossar · Testgrundlagen
Unit-Test
Englisch: Unit test
Auch genannt: Unittest, Modultest, Komponententest, Unit-Tests
Definition
Ein automatisierter Test, der ein kleines Stück Code wie eine Funktion oder Klasse isoliert von Datenbanken, Netzwerken und anderen Diensten prüft.
Ein Unit-Test (Modultest) prüft eine kleine Codeeinheit, typischerweise eine Funktion, Methode oder Klasse, und kontrolliert ihre Ausgabe oder ihr Verhalten für bestimmte Eingaben. Er läuft im Speicher, ohne echte Datenbanken, HTTP-Aufrufe oder Dateisysteme, dauert daher Millisekunden und schlägt aus genau einem Grund fehl. Unit-Tests bilden die Basis der Testpyramide und werden meist von Entwicklern zusammen mit dem Code geschrieben.
Beispiel (JUnit 5, Java 21)
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
class DiscountCalculatorTest {
private final DiscountCalculator calculator = new DiscountCalculator();
@ParameterizedTest
@CsvSource({ "99.99, 0.00", "100.00, 10.00", "250.00, 25.00" })
void appliesTenPercentFromOneHundred(double total, double expected) {
assertEquals(expected, calculator.discountFor(total), 0.001);
}
@Test
void rejectsNegativeTotals() {
assertThrows(IllegalArgumentException.class, () -> calculator.discountFor(-1));
}
}
Parametrisierte Tests benötigen das Artefakt junit-jupiter-params, das in der Sammelabhängigkeit junit-jupiter enthalten ist. (Echter Geldcode sollte BigDecimal statt double verwenden; hier ist es bewusst einfach gehalten.)
Was einen guten Unit-Test ausmacht
- Schnell und deterministisch. Keine Sleeps, Uhren, Zufallswerte oder Netzwerkzugriffe. Injizieren Sie eine feste
Clock, stattLocalDate.now()aufzurufen. - Isoliert. Abhängigkeiten werden durch Test Doubles ersetzt, wo sie den Test langsam oder unvorhersehbar machen würden.
- Ein Verhalten pro Test, mit einem Namen, der es benennt, sodass sich ein Fehlschlag selbst erklärt.
- Testet Verhalten, nicht Implementierung. Prüfen Sie Ausgaben und beobachtbare Effekte, nicht private Methoden, damit ein Refactoring keine Tests bricht.
Unit-Test vs. Integrationstest
Ein Unit-Test prüft Ihre Logik, während alles andere ersetzt ist. Ein Integrationstest prüft, ob echte Komponenten zusammenarbeiten: Ihr Repository gegen eine echte Datenbank, Ihr Client gegen einen echten (oder containerisierten) Dienst. Unit-Tests finden Logikfehler günstig; Integrationstests finden Fehler in Verdrahtung, Konfiguration, Serialisierung und Abfragen, die Unit-Tests wegmocken. Eine Suite nur aus Unit-Tests kann komplett grün sein, während die Anwendung nicht einmal startet.
Wie „Unit“ definiert wird
Es gibt keine allgemeingültige Antwort. Manche Teams betrachten eine einzelne Klasse als Unit und mocken alle Kollaborateure. Andere betrachten eine kleine Gruppe von Klassen, die gemeinsam ein Verhalten umsetzen, als Unit und ersetzen nur, was eine Prozessgrenze überschreitet. Der zweite Stil führt tendenziell zu Tests, die bei Refactorings weniger fragil sind.