- 1 Section
- 10 Lessons
- unbegrenzt
- Testen & Testmanagement10
- 1.1Warum testen? Fehlerkosten und V-Modell
- 1.2Teststufen: Unit, Integration, System, Abnahme
- 1.3Black-Box-Test: Äquivalenzklassen und Grenzwertanalyse
- 1.4White-Box-Test: Zweig- und Pfadüberdeckung
- 1.5TDD: Red-Green-Refactor
- 1.6Unit-Tests schreiben (JUnit / pytest)
- 1.7Mocking und Test-Doubles
- 1.8Testplan, Testprotokoll und Dokumentation
- 1.9Testergebnisse multimedial aufbereiten
- 1.10Aufgaben Testen
Mocking und Test-Doubles
In L6 hast du Unit-Tests in JUnit und pytest schreiben gelernt. Aber: ein Unit-Test soll isoliert sein. Was, wenn deine Klasse von einer Datenbank, einem E-Mail-Service oder einer Wetter-API abhängt? Diese externen Abhängigkeiten machen Tests langsam, instabil und teuer.
Die Lösung: Test-Doubles – Stell-Vertreter, die die echten Abhängigkeiten ersetzen. Die berühmteste Form heißt Mock, aber es gibt fünf verschiedene Typen, die in Klausuren gerne durchgemischt werden: Dummy, Stub, Spy, Mock, Fake. Diese Lektion entwirrt sie sauber.
1) Das Problem: echte Abhängigkeiten im Unit-Test
Stell dir vor, du willst eine Klasse OrderService testen. Sie ruft beim Bestellen einen E-Mail-Service auf, um eine Bestätigung zu schicken. Ohne Test-Doubles würde dein Test:
- Tatsächliche E-Mails verschicken (Spam an den Kunden bei jedem Testlauf!).
- Vom E-Mail-Server abhängen (außer Betrieb → roter Test).
- Sekunden statt Millisekunden brauchen.
- Nicht den OrderService testen, sondern die ganze Kette.
2) Test-Double – der Überbegriff
Test-Double ist die englische Übersetzung von „Filmstunt-Double" – der Stellvertreter, der die gefährliche Szene übernimmt, damit der echte Schauspieler unversehrt bleibt. Genau das tun sie im Test: sie übernehmen die Rolle einer realen Abhängigkeit.
Die berühmte Klassifikation von Gerard Meszaros unterscheidet fünf Typen. Sie werden gerne synonym verwendet, sind aber technisch verschieden:
3) Die fünf Test-Double-Typen im Detail
4) Vergleich auf einen Blick
| Typ | Rückgaben? | Aufrufe loggen? | Echte Logik? | Klassischer Einsatz |
|---|---|---|---|---|
| Dummy | – | – | – | Pflicht-Parameter, wird nie benutzt |
| Stub | ✓ | – | – | Pfad-Auswahl, festgelegte Antworten |
| Spy | ✓ | ✓ | ✓ (echt) | echtes Objekt + Aufrufprotokoll |
| Mock | ✓ | ✓ | – | Erwartungen prüfen |
| Fake | ✓ | – | ✓ (vereinfacht) | In-Memory-DB, Test-Auth |
5) Stubs vs. Mocks – die feine Linie
Die wichtigste Unterscheidung in Klausuren: Stub ist auf Eingabe fokussiert („was kommt zurück?"), Mock auf Ausgabe („was wurde aufgerufen?").
Beispiel anhand des OrderService:
- Stub-Test: „Wenn der Inventory-Stub 0 Stück zurückgibt, dann wirft OrderService eine OutOfStockException." – Stub gibt einen Wert vor, Test prüft Verhalten des SUT.
- Mock-Test: „Beim Aufruf von placeOrder soll der E-Mail-Mock genau einmal mit der richtigen Adresse aufgerufen werden." – Mock prüft, dass eine bestimmte Aktion stattfindet.
Stubs sind state-based: prüf den Endzustand. Mocks sind interaction-based: prüf die Interaktion.
6) Mock-Frameworks im Vergleich
Niemand baut Mocks von Hand – dafür gibt es spezialisierte Libraries:
mock(), when().thenReturn(), verify(). Spring-Integration top.MagicMock(), patch(). Mit pytest und pytest-mock fast unschlagbar.jest.fn(), jest.mock(). Sehr beliebt in React-Welt.7) Verbindung zu Integrationstests
In L2 hast du die Begriffe Stub und Treiber (Driver) bei Integrations-Strategien kennengelernt:
- Stub bei Top-Down-Integration ist ein Stellvertreter unter dem zu testenden Modul – simuliert eine noch nicht fertige Komponente und gibt Standard-Antworten zurück. Genau die gleiche Idee wie hier.
- Treiber ist das Gegenstück über dem Modul – simuliert den Aufrufer. Im Unit-Test-Kontext entspricht das dem Test selbst (er ruft die Methode auf).
Stub und Treiber sind also einfach spezielle Test-Doubles aus der Integrationstest-Welt.
8) Anti-Patterns beim Mocking
9) Praxis-Faustregel: wann mocken?
Eine gute Heuristik – mocke, wenn die Abhängigkeit ist:
- Langsam: Datenbank, Netzwerk, Filesystem.
- Unzuverlässig: externe APIs, Drittsysteme.
- Teuer: Zahlungs-APIs, SMS-Dienste.
- Schwer kontrollierbar: Zeit, Zufall, User-Eingaben.
- Mit Nebenwirkungen: echte E-Mails verschicken, Daten löschen.
Mocke nicht, wenn die Abhängigkeit schnell, deterministisch und harmlos ist (Wert-Objekte, Math, String-Utilities).
10) Dependency Injection als Voraussetzung
Damit Mocking überhaupt möglich ist, muss der Code Abhängigkeiten von außen reinbekommen können – nicht selbst erzeugen. Das ist das Prinzip der Dependency Injection (DI), eines der wichtigsten Design-Prinzipien moderner Software (vgl. K49 Entwurfsmuster).
Schlecht testbar: new EmailService() direkt in einer Methode aufrufen. Gut testbar: EmailService als Konstruktor-Parameter erhalten. Im Produktiv-Code wird der echte injiziert, im Test der Mock.
11) Klausur-Highlights
- Die 5 Test-Double-Typen nennen und unterscheiden können.
- Stub vs. Mock: Stub gibt Antworten, Mock prüft Interaktionen.
- Stub und Treiber im Integration-Test-Kontext (L2).
- Mockito (Java) und unittest.mock (Python) als Standard-Frameworks.
- Wann mocken? Langsame, unzuverlässige, teure Abhängigkeiten.
Zusammenfassung
Test-Doubles ersetzen echte Abhängigkeiten in Unit-Tests. Fünf Typen (Meszaros): Dummy (Platzhalter), Stub (vorgegebene Antworten), Spy (echtes Objekt + Aufrufprotokoll), Mock (Stub + Erwartungsprüfung), Fake (vereinfachte echte Implementation, z.B. In-Memory-DB). Stub = state-based, Mock = interaction-based. Frameworks: Mockito (Java), unittest.mock (Python), Sinon/Jest (JS). Voraussetzung: Dependency Injection. Nächste Lektion: Testplan und Testprotokoll.
