Einleitung: Warum void-Methoden für Anfänger eine Herausforderung sind?
\n\nHaben Sie jemals einen Unit-Test in Java mit Mockito geschrieben und sind plötzlich gegen eine Wand gelaufen? Es scheint alles einfach: Sie mocken ein Objekt, konfigurieren das Verhalten für Methoden, die etwas zurückgeben (einen String, eine Zahl, eine Liste). Aber sobald es um void-Methoden geht – solche, die nichts zurückgeben, sondern nur etwas intern tun (z. B. Daten speichern, eine E-Mail senden, eine Aktion protokollieren) – kommt der Stillstand.
\n\nWarum? Weil das gewohnte when(mock.someMethod()).thenReturn(something) hier nicht funktioniert. Der Compiler lässt Sie einfach nicht when(mock.voidMethod()).thenReturn(...) schreiben – eine void-Methode gibt nichts zurück, und thenReturn ist hier sinnlos.
Genau diese Frage – "How to mock void methods with Mockito" – hat tausende Aufrufe auf Stack Overflow gesammelt. Und heute werden wir sie ein für alle Mal klären. Sie lernen nicht nur, void-Methoden zu mocken, sondern dies auch richtig, elegant und schmerzfrei zu tun.
\n\nLos geht's! 🚀
\n\nWas ist eine void-Methode aus Testsicht?
\n\nEine void-Methode ist eine Methode, die eine Aktion ausführt, aber kein Ergebnis zurückgibt. Zum Beispiel:
\n\npublic class EmailService {\n public void sendWelcomeEmail(String email) {\n // hier die tatsächliche E-Mail-Versendung\n System.out.println("Sende E-Mail an " + email);\n }\n}\n\nIn einem echten Projekt möchten wir nicht, dass bei jedem Testlauf tatsächlich eine E-Mail gesendet wird. Wir müssen lediglich prüfen, ob die Methode aufgerufen wurde, oder ihre Ausführung unterdrücken, oder sie eine Ausnahme werfen lassen (um die Fehlerbehandlung zu testen).
\n\nDafür bietet Mockito eine spezielle Syntax mit doNothing(), doThrow(), doAnswer() und doCallRealMethod().
1. Der häufigste Fall: doNothing() – einfach eine void-Methode unterdrücken
\n\nWenn Sie möchten, dass eine void-Methode beim Aufruf nichts tut – verwenden Sie doNothing(). Dies ist das Standardverhalten von Mockito für void-Methoden, aber manchmal ist es hilfreich, es explizit anzugeben (z. B. für die Lesbarkeit oder bei Verwendung eines Spions).
import org.junit.jupiter.api.Test;\nimport org.junit.jupiter.api.extension.ExtendWith;\nimport org.mockito.Mock;\nimport org.mockito.junit.jupiter.MockitoExtension;\n\nimport static org.mockito.Mockito.*;\n\n@ExtendWith(MockitoExtension.class)\npublic class EmailServiceTest {\n\n @Mock\n private EmailService emailService;\n\n @Test\n void testDoNothing() {\n // Konfigurieren: Beim Aufruf von sendWelcomeEmail nichts tun\n doNothing().when(emailService).sendWelcomeEmail(anyString());\n\n // Methode aufrufen\n emailService.sendWelcomeEmail("test@example.com");\n\n // Prüfen, dass die Methode tatsächlich aufgerufen wurde\n verify(emailService).sendWelcomeEmail("test@example.com");\n }\n}\n\nWichtig: Wenn Sie @Mock verwenden, müssen Sie doNothing() nicht schreiben – Mockito macht void-Methoden standardmäßig zu "Attrappen". Aber wenn Sie @Spy (Spion) verwenden, wird die echte Methode aufgerufen, und doNothing() wird benötigt, um dies zu verhindern.
2. doThrow() – Einen Fehler in einer void-Methode simulieren
\n\nEine sehr häufige Aufgabe: Prüfen, wie Ihr Code reagiert, wenn der E-Mail-Versanddienst mit einem Fehler ausfällt. Dazu lassen wir die void-Methode eine Ausnahme werfen.
\n\n@Test\nvoid testDoThrow() {\n // Konfigurieren: Beim Aufruf von sendWelcomeEmail eine RuntimeException werfen\n doThrow(new RuntimeException("Fehler beim Senden der E-Mail"))\n .when(emailService).sendWelcomeEmail(anyString());\n\n // Beim Aufruf der Methode wird nun eine Ausnahme geworfen\n assertThrows(RuntimeException.class, () -> {\n emailService.sendWelcomeEmail("fail@example.com");\n });\n\n