Introduction : pourquoi les méthodes void sont-elles un casse-tête pour les débutants ?
\n\nAvez-vous déjà écrit un test unitaire en Java avec Mockito et soudainement heurté un mur ? Tout semble simple : on simule un objet, on configure le comportement pour les méthodes qui retournent quelque chose (une chaîne, un nombre, une liste). Mais dès qu'il s'agit de méthodes void — celles qui ne retournent rien, mais qui font quelque chose en interne (par exemple, sauvegarder des données, envoyer un email, journaliser une action) — on se retrouve bloqué.
\n\nPourquoi ? Parce que le classique when(mock.someMethod()).thenReturn(something) ne fonctionne pas ici. Le compilateur ne vous permettra tout simplement pas d'écrire when(mock.voidMethod()).thenReturn(...) — une méthode void ne retourne rien, et thenReturn n'a pas de sens.
C'est précisément cette question — "How to mock void methods with Mockito" — qui a cumulé des milliers de vues sur Stack Overflow. Et aujourd'hui, nous allons l'aborder une fois pour toutes. Vous apprendrez non seulement à simuler des méthodes void, mais aussi à le faire correctement, proprement et sans douleur.
\n\nC'est parti ! 🚀
\n\nQu'est-ce qu'une méthode void du point de vue des tests ?
\n\nUne méthode void est une méthode qui exécute une action, mais ne retourne pas de résultat. Par exemple :
\n\npublic class EmailService {\n public void sendWelcomeEmail(String email) {\n // ici, l'envoi réel de l'email\n System.out.println("Envoi de l'email à " + email);\n }\n}\n\nDans un projet réel, nous ne voulons pas qu'un email soit réellement envoyé à chaque exécution du test. Nous avons simplement besoin de vérifier que la méthode a été appelée, ou de stubber son exécution, ou de la forcer à lever une exception (pour tester la gestion des erreurs).
\n\nPour cela, Mockito fournit une syntaxe spéciale utilisant doNothing(), doThrow(), doAnswer() et doCallRealMethod().
1. Le cas le plus fréquent : doNothing() — simplement stubber une méthode void
\n\nSi vous avez besoin qu'une méthode void ne fasse rien lors de son appel — utilisez doNothing(). C'est le comportement par défaut de Mockito pour les méthodes void, mais il est parfois utile de le spécifier explicitement (par exemple, pour la lisibilité ou lors de l'utilisation d'un spy).
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 // Configuration : ne rien faire lors de l'appel de sendWelcomeEmail\n doNothing().when(emailService).sendWelcomeEmail(anyString());\n\n // Appel de la méthode\n emailService.sendWelcomeEmail("test@example.com");\n\n // Vérification que la méthode a bien été appelée\n verify(emailService).sendWelcomeEmail("test@example.com");\n }\n}\n\nImportant : Si vous utilisez @Mock, vous n'avez pas besoin d'écrire doNothing() — Mockito fait par défaut des méthodes void des "coquilles vides". Mais si vous utilisez @Spy (espion), la méthode réelle sera appelée, et doNothing() est nécessaire pour l'empêcher.
2. doThrow() — simuler une erreur dans une méthode void
\n\nUne tâche très courante : vérifier comment votre code réagit si le service d'envoi d'email échoue avec une erreur. Pour cela, nous forçons la méthode void à lever une exception.
\n\n@Test\nvoid testDoThrow() {\n // Configuration : lever une RuntimeException lors de l'appel de sendWelcomeEmail\n doThrow(new RuntimeException("Erreur d'envoi d'email"))\n .when(emailService).sendWelcomeEmail(anyString());\n\n // Désormais, l'appel de la méthode lèvera une exception\n assertThrows(RuntimeException.class, () -> {\n emailService.sendWelcomeEmail("fail@example.com");\n });\n\n