> ## Content Index
> Fetch the complete content index at: https://www.sfeir.dev/llms.txt
> Use this file to discover other available public pages before exploring further.

# Croquons du Mockito
- URL: https://www.sfeir.dev/back/croquons-du-mockito/
- Published: 2025-12-19T10:20:22.000Z
- Updated: 2025-12-19T10:20:22.000Z
- Description: Dans cet article, nous allons aborder les mocks (défini ci-après) et quelques bonnes pratiques à suivre de manière générale et leur mise en œuvre avec la librairie de mocking Java : Mockito.
- Author: Amin AOUDJIT
- Tags: Test, Mockito, Java, Kotlin, TU, Test unitaire, Spy, JUnit5, JUnit6, Mock, Back

## Introduction

L'écriture des tests unitaires ou d'intégration est une tâche cruciale et délicate en génie logiciel mais parfois fastidieuse. Elle nécessite une bonne connaissance des librairies et frameworks de tests et une bonne expérience en développement afin d'écrire des tests propres, maintenables dans le temps et qui serviront de documentation vivante pour les nouveaux arrivants sur le projet.

En Java comme dans d'autres langages, il existe une panoplie de librairies et de frameworks de tests et nous allons aborder la librairie [Mockito](https://en.wikipedia.org/wiki/Mockito?ref=sfeir.dev) en [JUnit](https://en.wikipedia.org/wiki/JUnit?ref=sfeir.dev) et les bonnes pratiques à suivre afin de bien s'en servir.

## Mockito - Définition

C'est une librairie permettant de mettre en place des substitutions aux objets (***mock object***), généralement coûteux à instancier, dans [les tests unitaires ](https://en.wikipedia.org/wiki/Unit%5Ftesting?ref=sfeir.dev)(TU). Sa puissance réside dans sa capacité à définir et simuler les comportements souhaités pour ensuite vérifier que ces interactions attendues sont belle et bien réalisées.

*Mockito* permet également de créer un remplaçant pour uniquement vérifier son comportement sans le besoin à le définir ou partiellement le définir. Ils appellent cette fonctionnalité de l'espionnage (***spying***) en créant un objet d'espionnage (***Spy object***) dans le cadre d'une substitution partielle (***partial mock***).

## Etapes du mock

Il y a quatre (4) étapes pour mocker en Mockito :

- Instancier un mock.
- Définir ses comportements : nous appelons cette action du **stubbing** (heurter en français).
- Réaliser les vérifications nécessaires.
- Accessoirement reset les mocks.

## Vocabulaire utilisé pour désigner un substituant

Il y a un superbe article de [Martin Fowler](https://martinfowler.com/articles/mocksArentStubs.html?ref=sfeir.dev) présentant les nuances concernant le terme **Mock Object** (object de mock) et qui cite ces cinq (5) types :

- **Dummy** objets bidon qui servent uniquement à remplir la liste des paramètres.
- **Fake** objets avec des implémentations partielles permettant de rendre un service et qui prend des raccourcis sur l'implémentation comme les bases de données en mémoire.
- **Stubs** fournissent des réponses préprogrammées à certains comportements uniquement.
- **Spies** substituants avec un enregistrement des appels qu'ils ont reçus.
- **Mocks** représentent les objets principaux des mocks, ils sont pré-programmés à certains comportements représentant des specifications de comments ils sont censés interagir avec leur environnement.

## Que doit-on mocker

Lors d'un TU nous nous concentrons uniquement sur l'entité faisant l'objet de test principalement une classe que nous testons [System Under Test](https://en.wikipedia.org/wiki/System%5Funder%5Ftest?ref=sfeir.dev) (SUT). Par conséquent, pour y arriver, nous avons besoin de l'isoler du monde extérieur et donc de ses dépendances en les mockants ou bouchonnants.

En effet, il est préférable de ne mocker que des objets définissant des **comportements** et généralement **coûteux à instancier** à cause de leurs dépendances avec d'autres objets de l'application, ils sont indisponibles, ils réalisent des opérations qui sont en dehors de notre cas de test, ils sont lents ou génèrent des résultats random (dans le nut de maîtriser le résultat). Parmi ce type d'objets, nous pouvons retrouver : les services, les stores, les objets d'accès au réseau ou au système externe, etc.

> Ne jamais bouchonner un objet de données comme un objet du domaine, [DTO](https://en.wikipedia.org/wiki/Data%5Ftransfer%5Fobject?ref=sfeir.dev) ou une entité[ DAO](https://en.wikipedia.org/wiki/Data%5Faccess%5Fobject?ref=sfeir.dev).

Il y a quelques objets complexes surtout dans le cadre de certains frameworks comme [Spring](https://spring.io/projects/spring-framework?ref=sfeir.dev). Ils sont souvent des contrats de réponse encapsulant un état complexe. D'habitude Spring fournit des adaptateurs à utiliser, sinon, il faudrait créer un adaptateur et/ou un builder pour faciliter leurs utilisations.

## Utiliser l'extension

Mockito met à disposition des développeurs Java utilisant *JUnit5* ou [*JUnit6*](https://www.sfeir.dev/back/junit-6-le-successeur-de-junit-5-est-la/) une extension [***MockitoExtension***](https://javadoc.io/doc/org.mockito/mockito-junit-jupiter/latest/org.mockito.junit.jupiter/org/mockito/junit/jupiter/MockitoExtension.html?ref=sfeir.dev) (l'équivalent de **MockitoJUnitRunner** pour les vintages de *JUnit4*) permettant d'initialiser les mocks, spies et les injecter dans l'objet SUT facilement avec uniquement des annotations ce qui rend le TU plus net avec moins de code.

Cette extension permet également un stubbing stricte c-à-d qu'elle va faire échouer le test si au moins un stubbing non nécessaire est configuré. C'est une très bonne chose car souvent ça mérite l'attention du développeur qui a mal estimé les comportements attendus ou un oublie lors d'un refactor de test. Ce mode stricte peut être allégé au besoin avec ***lenient***.

## Utiliser les annotations pour déclarer les mocks

Dans le but de simplifier l'initialisation et l'injection des mocks, il est préférable d'utiliser les annotations fournis pas Mockito. Il est également préférable de les utiliser avec l'extension ci-dessus qui permet de les parser et de les exploiter. Les annotations sont les suivantes (voici un article intéressant discutant les [annotations Spring](https://www.sfeir.dev/back/comprendre-les-annotations-dans-spring-boot/) dont celles de Mockito en Spring):

- ***@Mock*** permet de déclarer et initialiser un mock.
- ***@Spy*** permet de déclarer un spy (une initialisation de l'objet à surveiller est nécessaire).
- ***@InjectMocks*** permet de déclarer le STU en lui injectant les mocks instanciés via les annotations précédentes.

> Multiple injections n'est pas possible avec @InjectMocks

Si nous avons besoin d'injecter un mock à plusieurs endroits, nous sommes obligés de passer par l'initialisation à la main via ***Mockito.mock*** et ***Mockito.spy*** qui sont les équivalent des annotations de même nom ci-dessus.

## Utiliser verify et ses dérivés

Après les appels aux mocks, il est important de faire les vérifications avec ***Mockito.verify*** sur tous les mocks utilisés et s'assurer que les comportements attendus sont belle et bien conformes aux spécifications prédéfinies lors de la phase de stubbing.

Il y a également les dérivées intéressantes à *verify* qu'il faut aussi utiliser pour s'assurer qu'aucun autre comportement inattendu n'est déclenché en plus sur un mock et/ou aucune interaction n'a été enregistrée avec le mock en question en utilisant respectivement ***Mockito.verifyNoMoreInteractions*** et ***Mockito.verifyNoInteractions***.

## Utiliser les vraies valeurs attendues

Lorsque nous définissant les comportements (stubbing) et les vérifications, il est préférable dans la mesure du possible d'utiliser les vraies valeurs attendues en entrée et en sortie afin de s'assurer du vrai comportement de notre SUT en lieu et place des *matchers* génériques.

> Eviter l'utilisation des matchers ***Mockito.any*** et ses dérivés : ***Mockito.anyInt***, ***Mockito.anyFloat***, ***Mockito.anySet***, etc. dans le stubbing et les vérifications.

## Exemple d'utilisation de Mockito

###### Mockito en pratique

```java
@ExtendsWith(Mockitoextension.class) // 1. utilisation de l'extension
class PersonneServiceTest {
    @Mock // 2. déclaration de mock
    PersonneStore personneStore;
    @InjectMocks // 3. injection de mocks
    PersonneService personneService;
    
    @Test
    void add() {
        final Personne personToAdd = completePerson(); // 4. helper
        final Personne personAdded = completePerson(); // 4. helper
        final PersonneEntity personEntityToAdd = completePersonEntity(); // 4. helper
        final PersonneEntity personEntityAdded = completeAddedPersonEntity(); // 4. helper
        
       // 5. stubbing when(personneStore.add(personEntityToAdd)).thenReturn(personEntityAdded);
       
       // 6. appel du STU
       final Personne personAdded = personneService.add(personToAdd);
       
       // 7. assertion
        assertThat(personAdded)
            .usingRecursiveComparison()
            .isEqualTo(personAdded);
            
       // 8. vérifications
       verify(personneStore).add(personEntityToAdd);
       verifyNoMoreInteractions(personneStore);
    }
}

```

J'ai ajouté les numérotations dans le code en commentaire pour identifier les étapes pour tester un service de personne :

1. Utiliser l'annotation **MockitoExtension** avec *JUnit5 ou JUnit6*.
2. Déclaration de la dépendance ***PersonneStore*** comme mock avec ***@Mock***.
3. Déclaration du service à tester ***PersonneService*** en spécifiant qu'il a besoin qu'on lui injecte les mocks précédemment déclarés.
4. Initialisation des données *Fixtures* en recourant à des helpers réutilisables.
5. Stubbing du mock ***PersonneStore*** avec les valeurs attendues en entrée du service ***add*** et la valeur en retour (sortie).
6. Appel réel du service à tester ***PersonneService.add***.
7. Assertion en [***AssertJ***](https://assertj.github.io/doc/?ref=sfeir.dev) (librairie java pour les fluent assertions) pour vérifier le bon résultat de retour du service.
8. Réaliser les vérifications sur le mock ***PersonneStore*** afin de s'assurer qu'il n'y a que les comportements souhaités qui sont utilisés.

## Conclusion

Tout au long de cet article, nous avons exploré quelques bonnes pratiques à suivre lorsque nous substituants certains objets dans nos tests *TU* et en particulier en utilisant la librairie *Mockito* de Java.

Nous avons définit ce qu'est un **mock** et les différentes déclinaisons qu'il pourrait avoir. Ensuite, nous avons identifié les objets à mocker et par conséquent ceux qu'il faut impérativement éviter de mocker.

Enfin, nous avons évoqué ***Mockito*** avec son extension **MockitoExtension** à utiliser avec *JUnit5/JUnit6* et les différentes annotations que nous pouvons utiliser pour alléger le test et le rendre plus lisible à savoir ***@Mock***, ***@Spy*** et ***@InjectMocks***. De plus, nous avons insisté sur l'utilisation de vraies valeurs lors de stubbing avec ***Mockito.when*** et lors des vérifications avec ***Mockito.verify*** et ses dérivés ***Mockito.verifyNoMoreInteractions*** et ***Mockito.verifyNoInteractions***.

---

Autres articles à lire :

- [Et si on arrêtait de se mentir ! Soyons purs !](https://www.sfeir.dev/back/et-si-on-arretait-de-se-mentir-soyons-purs/)
- [L'enfer des types primitifs](https://www.sfeir.dev/lenfer-des-types-primitifs/)
- [Articles autour des tests](https://www.sfeir.dev/tag/test/)