| Prochaine révision | Révision précédente |
| eadl:bloc3:dev_av:tests:unit [2025/09/17 00:51] – créée jcheron | eadl:bloc3:dev_av:tests:unit [2025/09/17 15:38] (Version actuelle) – [Tests unitaires] jcheron |
|---|
| ====== Tests unitaires ====== | ====== Tests unitaires ====== |
| |
| On utilise souvent la matrice **Given-When-Then** : | On utilise souvent la matrice **Given-When-Then** (Structure AAA) : |
| | |
| | <sxh java;gutter:false> |
| | // Given (Arrange) - Préparer les données |
| | // When (Act) - Exécuter l'action |
| | // Then (Assert) - Vérifier le résultat |
| | </sxh> |
| | |
| | On isole le service à tester en utilisant des Mock objects (objets factices). |
| | |
| | * ''@Mock'' = Crée un objet factice (stub/mock) |
| | * Les repositories ne font rien de réel |
| | * leurs réponses sont contrôlées avec **when(...).thenReturn(...)** |
| | * ''@InjectMocks'' = Crée la vraie instance à tester |
| | |
| | Vérification du WorkFlow métier : |
| | |
| | * ''verify()'' : "Le service a-t-il bien appelé cette méthode ?" |
| | * ''verifyNoInteractions()'' : "Le service n'a-t-il pas touché ce repository ?" |
| | |
| | **Exemple :** |
| | |
| | Si la catégorie n'existe pas → le service ne doit PAS essayer de sauver le produit ! |
| | |
| | ===== Bonnes pratiques ===== |
| | * 1 test = 1 comportement |
| | * Noms explicites (should create product when category exists) |
| | * Tests indépendants (pas d'ordre) |
| | * Données de test isolées |
| | * Given-When-Then structure |
| | === FIRST === |
| | |
| | == Fast == |
| | Feeback rapide après lancement de la suite |
| | |
| | == Independant == |
| | Ne pas faire dépendre un test du résultat d'autres tests, ni de l'environnement |
| | |
| | == Repeatable == |
| | Un test doit toujours produire le même résultat, prédictible |
| | |
| | == Self-validating == |
| | Doit être autonome pour déterminer la validité de son résultat |
| | |
| | == Timely == |
| | Fait au bon moment (avant l'écriture du code de prod dans l'idéal) |
| | |
| | |
| | ===== Ressources ===== |
| | |
| | ==== Annotations Spring/Mockito ==== |
| | |
| | <sxh java;gutter:false> |
| | @ExtendWith(MockitoExtension::class) // Pour tests unitaires |
| | @SpringBootTest // Application complète |
| | @WebMvcTest(Controller::class) // Tests controllers |
| | @DataJpaTest // Tests repositories |
| | @Mock // Faux objet |
| | @MockBean // Mock dans contexte Spring |
| | @InjectMocks // Vraie instance avec mocks injectés |
| | </sxh> |
| | |
| | ==== Mocking concepts ==== |
| | |
| | * **when().thenReturn()** : Programmer les réponses |
| | * **verify()** : Vérifier les appels |
| | * **verifyNoInteractions()** : Aucune interaction |
| | * **any()** : Matcher générique |
| | |
| | ==== Assertions usuelles ==== |
| | |
| | <sxh java;gutter:false> |
| | assertThat(result).isNotNull() |
| | assertThat(result.name).isEqualTo("expected") |
| | assertThat(result.price).isEqualByComparingTo(BigDecimal("10.50")) |
| | assertThatThrownBy { ... }.isInstanceOf(Exception::class.java) |
| | </sxh> |
| |
| ===== Exemple de test ===== | ===== Exemple de test ===== |