Différences
Ci-dessous, les différences entre deux révisions de la page.
| Prochaine révision | Révision précédente | ||
| eadl:bloc3:dev_av:td2-b [2025/10/08 00:30] – créée jcheron | eadl:bloc3:dev_av:td2-b [2025/10/08 01:32] (Version actuelle) – [10. Exercice pratique] jcheron | ||
|---|---|---|---|
| Ligne 18: | Ligne 18: | ||
| === 2.1 Dépendances Maven === | === 2.1 Dépendances Maven === | ||
| - | <code xml> | + | <sxh xml> |
| < | < | ||
| <!-- Spring Boot Test (inclut JUnit 5, Mockito, AssertJ) --> | <!-- Spring Boot Test (inclut JUnit 5, Mockito, AssertJ) --> | ||
| Ligne 42: | Ligne 42: | ||
| </ | </ | ||
| </ | </ | ||
| - | </code> | + | </sxh> |
| === 2.2 Configuration de test (application-test.properties) === | === 2.2 Configuration de test (application-test.properties) === | ||
| - | <code properties> | + | <sxh bash> |
| # src/ | # src/ | ||
| Ligne 68: | Ligne 68: | ||
| logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE | logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE | ||
| logging.level.org.hibernate.orm.jdbc.bind=TRACE | logging.level.org.hibernate.orm.jdbc.bind=TRACE | ||
| - | </code> | + | </sxh> |
| ==== 3. Anatomie d'un test JPA ==== | ==== 3. Anatomie d'un test JPA ==== | ||
| Ligne 74: | Ligne 74: | ||
| === 3.1 Test Repository basique === | === 3.1 Test Repository basique === | ||
| - | <code java> | + | <sxh java> |
| @DataJpaTest | @DataJpaTest | ||
| @ActiveProfiles(" | @ActiveProfiles(" | ||
| Ligne 103: | Ligne 103: | ||
| } | } | ||
| } | } | ||
| - | </code> | + | </sxh> |
| <WRAP round tip> | <WRAP round tip> | ||
| Ligne 114: | Ligne 114: | ||
| === 3.2 TestEntityManager - Les commandes clés === | === 3.2 TestEntityManager - Les commandes clés === | ||
| - | <code java> | + | <sxh java> |
| @Test | @Test | ||
| void demonstrateTestEntityManager() { | void demonstrateTestEntityManager() { | ||
| Ligne 134: | Ligne 134: | ||
| entityManager.detach(fromDb); | entityManager.detach(fromDb); | ||
| } | } | ||
| - | </code> | + | </sxh> |
| ==== 4. Tests des associations ==== | ==== 4. Tests des associations ==== | ||
| Ligne 140: | Ligne 140: | ||
| === 4.1 OneToMany bidirectionnel === | === 4.1 OneToMany bidirectionnel === | ||
| - | <code java> | + | <sxh java> |
| @Test | @Test | ||
| void shouldCascadeOrderToOrderItems() { | void shouldCascadeOrderToOrderItems() { | ||
| Ligne 166: | Ligne 166: | ||
| .containsExactlyInAnyOrder(" | .containsExactlyInAnyOrder(" | ||
| } | } | ||
| - | </code> | + | </sxh> |
| === 4.2 Problème N+1 - Détection === | === 4.2 Problème N+1 - Détection === | ||
| - | <code java> | + | <sxh java> |
| @Test | @Test | ||
| void shouldDetectNPlusOneProblem() { | void shouldDetectNPlusOneProblem() { | ||
| Ligne 210: | Ligne 210: | ||
| // assertSelectCount(1); | // assertSelectCount(1); | ||
| } | } | ||
| - | </code> | + | </sxh> |
| ==== 5. Tests des requêtes JPQL ==== | ==== 5. Tests des requêtes JPQL ==== | ||
| Ligne 216: | Ligne 216: | ||
| === 5.1 Query basique === | === 5.1 Query basique === | ||
| - | <code java> | + | <sxh java> |
| @Test | @Test | ||
| void shouldFindProductsByPriceRange() { | void shouldFindProductsByPriceRange() { | ||
| Ligne 237: | Ligne 237: | ||
| .containsExactly(" | .containsExactly(" | ||
| } | } | ||
| - | </code> | + | </sxh> |
| === 5.2 Projection DTO === | === 5.2 Projection DTO === | ||
| - | <code java> | + | <sxh java> |
| public record ProductSummary(UUID id, String name, BigDecimal price) {} | public record ProductSummary(UUID id, String name, BigDecimal price) {} | ||
| Ligne 263: | Ligne 263: | ||
| assertThat(summaries.get(0).name()).isEqualTo(" | assertThat(summaries.get(0).name()).isEqualTo(" | ||
| } | } | ||
| - | </code> | + | </sxh> |
| ==== 6. Tests avec données initiales ==== | ==== 6. Tests avec données initiales ==== | ||
| Ligne 269: | Ligne 269: | ||
| === 6.1 Via fichier SQL === | === 6.1 Via fichier SQL === | ||
| - | <code java> | + | <sxh java> |
| @Test | @Test | ||
| @Sql("/ | @Sql("/ | ||
| Ligne 276: | Ligne 276: | ||
| assertThat(products).hasSizeGreaterThan(0); | assertThat(products).hasSizeGreaterThan(0); | ||
| } | } | ||
| - | </code> | + | </sxh> |
| Fichier '' | Fichier '' | ||
| - | <code sql> | + | <sxh sql> |
| INSERT INTO product (id, name, price, stock) VALUES | INSERT INTO product (id, name, price, stock) VALUES | ||
| (' | (' | ||
| (' | (' | ||
| - | </code> | + | </sxh> |
| === 6.2 Via méthode @BeforeEach === | === 6.2 Via méthode @BeforeEach === | ||
| - | <code java> | + | <sxh java> |
| @DataJpaTest | @DataJpaTest | ||
| class OrderRepositoryTest { | class OrderRepositoryTest { | ||
| Ligne 315: | Ligne 315: | ||
| } | } | ||
| } | } | ||
| - | </code> | + | </sxh> |
| ==== 7. Tests des contraintes ==== | ==== 7. Tests des contraintes ==== | ||
| Ligne 321: | Ligne 321: | ||
| === 7.1 Validation Bean Validation === | === 7.1 Validation Bean Validation === | ||
| - | <code java> | + | <sxh java> |
| @Test | @Test | ||
| void shouldFailWhenEmailInvalid() { | void shouldFailWhenEmailInvalid() { | ||
| Ligne 337: | Ligne 337: | ||
| .hasMessageContaining(" | .hasMessageContaining(" | ||
| } | } | ||
| - | </code> | + | </sxh> |
| === 7.2 Contrainte unique === | === 7.2 Contrainte unique === | ||
| - | <code java> | + | <sxh java> |
| @Test | @Test | ||
| void shouldFailOnDuplicateEmail() { | void shouldFailOnDuplicateEmail() { | ||
| Ligne 357: | Ligne 357: | ||
| .isInstanceOf(DataIntegrityViolationException.class); | .isInstanceOf(DataIntegrityViolationException.class); | ||
| } | } | ||
| - | </code> | + | </sxh> |
| ==== 8. Testcontainers (DB réelle) ==== | ==== 8. Testcontainers (DB réelle) ==== | ||
| - | <code java> | + | <sxh java> |
| @DataJpaTest | @DataJpaTest | ||
| @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) | @AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE) | ||
| Ligne 391: | Ligne 391: | ||
| } | } | ||
| } | } | ||
| - | </code> | + | </sxh> |
| ==== 9. Bonnes pratiques ==== | ==== 9. Bonnes pratiques ==== | ||
| Ligne 412: | Ligne 412: | ||
| ==== 10. Exercice pratique ==== | ==== 10. Exercice pratique ==== | ||
| - | <WRAP round box> | + | <WRAP round todo> |
| **À implémenter :** | **À implémenter :** | ||
| Créer les tests d' | Créer les tests d' | ||
| - | - [ ] Test de création d'une review avec associations | + | - Test de création d'une review avec associations |
| - | - [ ] Test de la contrainte '' | + | - Test de la contrainte '' |
| - | - [ ] Test unicité (user, product) | + | - Test unicité (user, product) |
| - | - [ ] Test du chargement avec '' | + | - Test du chargement avec '' |
| - | - [ ] Test de calcul de moyenne des ratings par produit | + | - Test de calcul de moyenne des ratings par produit |
| - | - [ ] Test de la projection '' | + | - Test de la projection '' |
| </ | </ | ||