Start / Seminare / Java Testing mit JUnit, Mockito und Testcontainers

Modul

Fortgeschrittenes Stubbing und schwierige Abhängigkeiten

4 Kapitel in diesem Modul-Video · Laufzeit

Vertonung mit synthetischer Stimme · Inhalte redaktionell verantwortet · © 2026 HECKER CONSULTING, alle Rechte vorbehalten

Transkript

Der gesprochene Text dieses Moduls zum Mitlesen, Überfliegen und Durchsuchen. Ein Klick auf einen Zeitstempel springt an die Stelle im Video.

Fortgeschrittenes Stubbing

0:00 In diesem Modul geht es um die Werkzeuge, mit denen Mockito auch das ersetzen kann, was eigentlich unersetzbar wirkt: statische Methoden, finale Klassen, Konstruktoraufrufe, sogar Enum-Konstanten. Das ist technisch beeindruckend, und ich möchte trotzdem eine Warnung voranstellen, die Sie auf der Titelfolie schon lesen: Dass Mockito das kann, ist kein Grund, es zu tun.

0:21 Wir sehen uns diese Werkzeuge gründlich an — und jedes Mal auch die Frage, was der Bedarf danach über die Anwendung aussagt. Diese Frage führt uns direkt ins nächste Modul.

Fortgeschrittenes Stubbing und schwierige Abhängigkeiten

0:32 Drittes Modul des Mockito-Tages. Wir beginnen mit dynamischen Antworten und Spies, gehen dann an statische Methoden und Konstruktoren, und schließen mit der Strictness — der Einstellung, die Mockito von einem stillen zu einem redseligen Werkzeug macht.

Dynamische Antworten und Spies

0:47 Fangen wir mit dem Fall an, in dem eine feste Antwort nicht reicht: wenn das Ergebnis vom Argument abhängt. Bisher haben wir gesagt: Wenn so gerufen wird, gib das zurück. Jetzt wird aus dem festen Wert eine Funktion, die aus dem Aufruf die Antwort berechnet. Das ist praktisch, wenn Ihre Attrappe eine Referenz zurückgeben soll, die zur Anfrage passt.

1:08 Der Spy ist der zweite Fall: Er umhüllt ein echtes Objekt, alle Methoden laufen echt — bis Sie eine davon stubben. Damit ersetzen Sie einen Teil eines Objekts statt des ganzen. Das nennt sich partielles Mocking und ist ein wertvolles Werkzeug, gerade in Altcode, der noch keine sauberen Schnittstellen hat. Oben sehen Sie das Muster: Die Antwort greift auf das übergebene Argument zu und baut daraus die Referenz.

1:32 So verhält sich die Attrappe wie der echte Dienst, ohne dass Sie je Test einen eigenen Rückgabewert vorbereiten müssen. Unten steht ein Detail, das ich Ihnen dick unterstreichen möchte: Beim Spy immer die umgekehrte Schreibweise mit doReturn. Die gewohnte Form würde die echte Methode bereits beim Stubben aufrufen — und wenn diese Methode etwas speichert, verschickt oder Geld bewegt, ist es passiert, bevor der Test überhaupt begonnen hat.

1:56 Hier lässt sich viel Laufzeit sparen. Ein asynchrones Ergebnis muss im Test nicht asynchron sein: Sie geben ein bereits abgeschlossenes Ergebnis zurück, und der Code läuft durch. Callbacks rufen Sie in der Antwort direkt auf, statt auf einen Thread zu warten. Wer stattdessen im Test schlafen legt, kauft Sekunden Laufzeit für eine Zusage, die trotzdem unsicher bleibt — auf einem langsamen Build-Agenten reichen die zwei Sekunden dann doch nicht.

2:21 Für echte Nebenläufigkeit gibt es eine Verifikation mit Zeitfenster, aber die bleibt die zweite Wahl. Diese Tabelle sammelt die Fälle, in denen eine einfache Antwort nicht genügt. Interessant ist die zweite Zeile: Bei generischen Rückgabetypen ist eine berechnete Antwort oft sauberer als ein fester Wert mit einer Typumwandlung, die der Compiler nur widerwillig durchwinkt.

2:43 Der Hinweis in der Fußzeile ist mir wichtiger als die Tabelle selbst: Eine Antwortfunktion, die länger als drei Zeilen wird, ist in Wahrheit ein Fake, der noch keine Klasse hat. Machen Sie in dem Fall eine Klasse daraus. Sie ist testbar, benennbar und in zehn anderen Tests wiederverwendbar. Der erste Punkt ist die Spy-Falle, die wir eben gesehen haben — mit echtem Nebeneffekt.

3:04 Der zweite ist der schleichende: Die Antwortfunktion baut die halbe Fachlogik nach und wird nicht mit dem Original synchron gehalten. Dann testen Sie gegen eine veraltete Kopie Ihrer eigenen Regeln. Der dritte ist ein handfestes Problem — ein Spy erzeugt eine echte Instanz, und wenn deren Konstruktor etwas Aufwendiges tut, tut er es auch im Test.

3:24 Und der vierte ist ein Java-Detail: Der Zugriff auf ein Argument ohne Typangabe scheitert erst zur Laufzeit, mit einer wenig hilfreichen Meldung.

Statisches, Finales und Konstruktoren

3:33 Jetzt kommt das Notfallwerkzeug. Ich nenne es bewusst so — es ist nützlich, und es hat ein Verfallsdatum. Seit Mockito 5 ist der Inline Mock Maker die Voreinstellung. Das ist ein wichtiger Satz, weil er eine alte Wahrheit ablöst: Früher brauchte man für finale Klassen und statische Methoden eine Zusatzbibliothek, oft mit schlechtem Ruf.

3:54 Heute geht das mit Mockito selbst. Statische Methoden ersetzen Sie in einem klar begrenzten Bereich, Konstruktoraufrufe ebenso, und seit Version 5.22 auch Singletons wie Enum-Konstanten. Neu in 5.23 ist die statische Variante des Spy — echte statische Methoden laufen weiter, bis Sie eine davon gezielt ersetzen. Das ist deutlich schonender als ein vollständiger statischer Mock.

4:17 Das Entscheidende an diesem Block ist die Klammer. Der statische Mock lebt nur innerhalb des Blocks — danach verhält sich die Klasse wieder wie immer. Deshalb gehört er immer in ein try-with-resources, ohne Ausnahme. Der zweite wichtige Punkt steht in der Fußzeile: Der Mock gilt nur im aktuellen Thread. Das ist eine bewusste Designentscheidung von Mockito, damit sich parallel laufende Tests nicht gegenseitig die statische Welt umbauen.

4:42 Es heißt aber auch: Wenn Ihr Prüfling die Arbeit an einen anderen Thread abgibt, greift der Mock dort nicht. Diese Folie ist der praktische Stolperstein des Jahres. Seit Java 21 dürfen Bibliotheken keinen Java-Agenten mehr an die eigene laufende Maschine hängen — das hat die Java-Plattform bewusst eingeschränkt. Der Inline Mock Maker braucht aber genau das. Die Folge: Er funktioniert nur noch sauber, wenn Sie Mockito ausdrücklich als Agent auf der Kommandozeile mitgeben.

5:11 Fehlt das, gibt die Maschine bei jedem Testlauf eine Warnung aus, und irgendwann wird sie zum Fehler. Auf Java 21 oder 25 gehört dieser Eintrag also zur Grundeinrichtung des Builds, nicht zur Kür. Diese Tabelle ist die eigentliche Botschaft des Moduls. Links steht jeweils, was gemockt werden soll — rechts die Antwort, die meistens besser ist. Statische Uhr?

5:34 Reichen Sie die Zeit hinein, wie im fünften Modul. Konstruktoraufruf im Prüfling? Nehmen Sie eine Fabrik oder einen Konstruktorparameter. Finale Fremdklasse? Legen Sie eine eigene, schmale Schnittstelle davor. Enum mit Verhalten? Ziehen Sie das Verhalten heraus. Alle vier Fälle gehen mit Mockito, keine Frage. Und alle vier sind zugleich ein Befund über die Produktionsarchitektur — genau darüber sprechen wir im nächsten Modul.

6:02 Der erste Punkt ist der teuerste dieses Moduls: Ein statischer Mock, der nicht geschlossen wird, beeinflusst alle folgenden Tests desselben Threads. Die Fehlersuche dauert lange, weil der Verursacher woanders steht als der Fehler. Der zweite ist die Thread-Begrenzung, die wir eben besprochen haben. Der dritte ist der fehlende Agent, dessen Warnung jahrelang als Rauschen durchgeht — bis ein Java-Update daraus einen Fehler macht.

6:26 Und der vierte ist die Breitenwirkung: Ein Konstruktor-Mock ersetzt jede Erzeugung dieses Typs im Block, auch die, an die niemand gedacht hat.

Strictness und übersichtliche Fixtures

6:34 Zum Schluss ein Thema, das anfangs nervt und nach zwei Wochen niemand mehr missen möchte: strenge Stubs. Mit strengen Stubs meldet Mockito zwei Dinge. Erstens: Sie haben etwas vorbereitet, das kein Test benutzt hat. Zweitens: Ihr Code hat gerufen, aber mit anderen Argumenten als vorbereitet. Beide Meldungen sind kleine Geschenke, auch wenn sie sich zunächst nicht so anfühlen.

6:58 Die Jupiter-Extension arbeitet standardmäßig streng. Für einzelne Ausnahmen gibt es die nachsichtige Variante an einem einzelnen Stub, und für ganze Klassen eine Einstellung. Die Reihenfolge ist wichtig: erst der einzelne Stub, dann die Klasse — und die Klasse eigentlich nie. Oben sehen Sie, wie eine ganze Klasse auf nachsichtig gestellt wird. Ich zeige Ihnen das ausdrücklich als Warnung, nicht als Empfehlung — die Fußzeile nennt es einen Schuldschein.

7:25 Unten steht die Variante, die ich vertreten kann: ein einzelner Stub als nachsichtig markiert, mit einer sichtbaren Begründung direkt daneben. Der Unterschied ist nicht technisch, sondern sozial: Die untere Fassung zwingt Sie, für genau diesen einen Fall eine Entscheidung zu treffen. Die obere schaltet die Diagnose für dreißig Tests ab, weil einer davon gestört hat.

7:46 Es lohnt sich, die beiden Meldungen auseinanderzuhalten. Ein ungenutzter Stub heißt fast immer: Der Test prüft etwas anderes als gedacht — der Weg durch den Code war ein anderer. Ein Argument-Mismatch heißt: Der Prüfling ruft anders auf, als der Test annimmt, und zwar meistens seit dem letzten Umbau. Ohne strenge Stubs endet beides in einer Nullzeigerausnahme drei Zeilen später, und Sie fangen bei null an.

8:10 Wer diese Meldungen abschaltet, gewinnt Ruhe im Testlauf und verliert genau die Information, die er später sucht. Der zweite Teil dieses Kapitels ist eine Frage der Hygiene. Stubs im gemeinsamen Aufbau gelten für alle Tests der Klasse — und werden von den wenigsten gebraucht. Sie wachsen still, weil jeder neue Test einen weiteren beisteuert und niemand aufräumt.

8:32 Der Anspruch sollte sein: Ein Test zeigt seine Voraussetzungen selbst, nicht dreißig Zeilen weiter oben. Wiederkehrende Aufbauten gehören in benannte Methoden mit sprechenden Namen. Und wenn der Aufbau länger ist als der Test, dann prüft niemand mehr, was eigentlich gilt — dann liest man nur noch Vorbereitung. Der erste Punkt ist die Klasse auf nachsichtig, weil ein einziger Stub störte — mit Kollateralschaden für alle anderen.

8:58 Der zweite ist die schnelle Reparatur ohne Erkenntnis: Ungenutzte Stubs werden entfernt, ohne zu fragen, warum sie ungenutzt waren. Oft steckt dahinter ein Test, der einen anderen Pfad nimmt als gedacht. Der dritte ist der vorsorgliche Aufbau, der alles stubbt, was irgendein Test brauchen könnte. Und der vierte ist eine Haltungsfrage: Wer strenge Stubs als Schikane empfindet, schaltet sie ab — und zahlt den nächsten Fehler mit einer Stunde Debugger.

Übung

9:24 In der Übung lösen wir dieselbe Altlast zweimal — einmal mit dem Notfallwerkzeug und einmal richtig. Und dann vergleichen wir. Der Lieferfenster-Prüfer von Krautgut fragt die Systemzeit über eine statische Methode ab — ein sehr typischer Fund in gewachsenem Code. Ihre Aufgabe ist, das Problem zweimal zu lösen: einmal mit einem statischen Mock, einmal durch Umbau. Beide Fassungen sollen grün sein.

9:49 Und dann kommt der eigentliche Teil: Sie notieren die Unterschiede in Laufzeit, Lesbarkeit und Kopplung und entscheiden sich begründet für eine. Diese Übung ist bewusst so gebaut, dass Sie das Notfallwerkzeug einmal benutzt haben — man argumentiert leichter gegen etwas, das man kennt. Schritt eins ist die Einrichtung mit dem Agenten, und ich sage gleich dazu: Das wird nicht auf Anhieb sauber laufen.

10:13 Genau das ist der Lerneffekt — Sie erleben, was der Java-21-Wandel praktisch bedeutet. Schritt zwei ist der statische Mock, sauber begrenzt. Schritt drei greift auf die Uhr-Extension aus dem fünften Modul zurück. Schritt vier misst, statt zu schätzen: Laufzeit und Zeilenzahl. Und Schritt fünf ist die Entscheidung mit Begründung. Halten Sie sie schriftlich fest — im echten Projekt ist genau das die Notiz, die man ein Jahr später sucht.

10:40 Der erste Punkt ist der Mock ohne try-with-resources, der die Folgetests einfärbt — passiert in dieser Übung erfahrungsgemäß mindestens einmal. Der zweite ist die Entscheidung nach Gefühl statt nach Zahlen; deshalb steht Messen ausdrücklich im Vorgehen. Der dritte ist Bequemlichkeit: Die zweite Fassung wird gar nicht gebaut, weil die erste ja funktioniert. Damit entfällt genau der Vergleich, um den es geht.

11:03 Und der vierte hat es in sich: Die Agent-Einrichtung landet nur lokal und fehlt in der Pipeline. Dann läuft es auf Ihrem Rechner und nirgendwo sonst.

Lieber mit Trainer? Dieses Modul ist Teil unserer Team-Schulungen — mit Übungen, Ihrem eigenen Code und Fragen, die ein Video nicht beantwortet. Mehr erfahren →