Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Spring — Exemples de Mocks et de Tests

Projet pédagogique qui illustre, étape par étape, comment tester du code Java avec JUnit 5, Mockito et Spring Boot Test.

L'objectif n'est pas de tester une « vraie » application, mais de rendre visibles les mécanismes : mock, spy, injection, cycle de vie, assertions et pièges courants.

Le code testé

Trois couches qui se délèguent le travail, du plus haut niveau au plus bas :

CalculatorService  ──►  MathHelper  ──►  ToMockHelper
   (service)             (logique)        (valeurs fixes)
  • ToMockHelper renvoie des valeurs fixes (10, 20, 10 + 20). C'est le candidat parfait à « remplacer » dans un test.
  • MathHelper fait de l'arithmétique et délègue à ToMockHelper.
  • CalculatorService est le service exposé ; il délègue à MathHelper.

Cette chaîne de dépendances est ce qui permet d'illustrer proprement les mocks : on teste une couche en remplaçant celle du dessous.

Parcours d'apprentissage

Il y a deux pistes parallèles qui enseignent EXACTEMENT les mêmes notions (AE, à lire dans l'ordre) :

  • 🧮 Piste Brutal (les maths) — package com.sbp.testing : des nombres nus (add(2,3)=5). Sans détour, mais abstrait. Fichiers préfixés *_Brutal_*.
  • Piste Soft (le café) — package com.sbp.testing.soft : une histoire de café (un café 3 €, un croissant 2 €, une formule 5 €, une caisse, un catalogue de prix). Commencez par celle-ci si les nombres nus vous semblent abstraits : les valeurs ont enfin un sens. Fichiers préfixés *_Soft_*.

Le nom de chaque classe annonce donc sa piste : A_Brutal_ExempleSimple (maths) et A_Soft_ExempleConcret (café) enseignent la même chose. Choisissez celle qui vous parle ; chaque fichier AE a son équivalent dans l'autre piste.

Notion Piste abstraite Piste concrète (café) Spring ?
Bases : mock, spy, assertions, pièges, assertThrows, verify, AssertJ A_Brutal_ExempleSimple A_Soft_ExempleConcret
Cycle de vie JUnit + piège du spy non câblé (✅/❌) B_Brutal_BeforeAndAfter B_Soft_CycleDeVie ✅ (@Autowired)
@Mock + @InjectMocks, matchers, ArgumentCaptor C_Brutal_Injected C_Soft_Injection ❌ (MockitoExtension)
Mock partiel avec @Spy : vrai code vs stub D_Brutal_Spy D_Soft_Espion ❌ (MockitoExtension)
Intégration Spring : @MockitoBean remplace un bean E_Brutal_MockitoBean E_Soft_BeanRemplace ✅ (obligatoire)

Le code testé, côté café

CommandeService  ──►  Caisse  ──►  CataloguePrix
  (le client)         (calcule)     (prix externes : BD/API -> à mocker)

Le CataloguePrix illustre POURQUOI on mocke : en vrai ses prix viennent d'une base de données ou d'une API qu'on ne veut pas appeler dans un test. Et la méthode Caisse.encaisser(...) a un effet de bord visible (« Encaissement RÉEL ») : elle sert à montrer, en direct dans la console, le danger du when() sur un espion (voir A_Soft_ExempleConcret#espion_pourquoiDoReturn).

Mock vs Spy — en une phrase

  • Mock : coquille vide. Toutes les méthodes renvoient une valeur par défaut (0, null, false) tant qu'on ne les stubbe pas.
  • Spy : objet réel enveloppé. Il exécute le vrai code, sauf pour les méthodes qu'on stubbe explicitement (« mock partiel »).

Le piège du spy (à retenir)

Sur un spy, préférez doReturn(...).when(spy).methode(...) plutôt que when(spy.methode(...)).thenReturn(...) : la seconde forme appelle réellement spy.methode(...) pendant le stubbing, ce qui peut déclencher des effets de bord. Voir A_Brutal_ExempleSimple#spy_pourquoiDoReturn.

@SpringBootTest : à utiliser avec parcimonie

@SpringBootTest démarre tout le contexte Spring : c'est lent. Ne l'utilisez que lorsque vous testez réellement l'intégration Spring (@Autowired, @MockitoBean). Pour un simple test de logique avec des mocks, préférez @ExtendWith(MockitoExtension.class) (voir C et D).

Lancer les tests

./mvnw test

⚠️ Chaque piste contient un test qui échoue volontairement (A_Brutal_ExempleSimple#echoueVolontairement et A_Soft_ExempleConcret#echoueVolontairement). C'est intentionnel : ils sont là pour vous faire voir à quoi ressemble un échec et pourquoi une assertion fausse casse la construction. Ils sont isolés et clairement étiquetés (❌ dans leur @DisplayName).

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages