Maximize Page
Tech & DevOps HubEspace Tech & DevOps: Explorez le monde du Dev, du Cloud et des outils DevOps à travers nos articles et discussions Explore the world of development, the cloud and DevOps tools

Stratégie de tests unitaires

Date de l'article:01-10-2025
Spring Boot
On pose la première brique de la qualité logicielle on construisant les tests unitaires à partir du code. L'objectif n'est pas seulement de tester du code, mais de rendre le build déterministe, rapide et fiable dans le pipeline
Place des tests dans le cycle de développement

Dans un projet Spring Boot, les tests unitaires sont écrits en parallèle du code applicatif : services, contrôleurs, repositories

Ils servent à:
  • Valider la logique métier
  • Détecter les régressions immédiatement
  • Sécuriser les refactorings
Le build casse si une règle fonctionnelle est rompue
Ils s'exécutent:
  • En continu pendant le développement
  • A chaque commit dans le pipeline CI
  • Avant toute livraison

TDD (Test Drive Development) vs Approche pragmatique

Elles représentent deux philosophies différentes dans la gestion de la qualité et du temps de développement.
Le TDD est une méthode axée sur les tests et se caractérise par une approche pédagogique ou évaluative rigide, où le savoir est imposé comme une vérité absolue et vérifié par des évaluations standardisées, tandis que l'approche pragmatique privilégie le contexte et la valeur métier immédiate.


TDD strict (Red → Green → Refactor)
Consiste à:
1. Écrire un test minimal qui échoue (rouge)
2. Écrire juste assez de code pour passer le test (vert)
3. Nettoyer/Refactoriser
Principe fort : Ne jamais écrire de code de production sans test associé
Résultat: → code découplé, meilleure couverture, design orienté testabilité
Approche pragmatique (souvent utilisée en entreprise)
Consiste à:
1. Écrire la méthode
2. Écrire immédiatement les tests
3. Passer à la feature suivante

Objectif: feedback rapide et détection précoce des bugs


Stratégie globale de tests (pyramide)
Dans cet article, on regroupe sous "tests unitaires"
  • unit tests stricts (Mockito pur)
  • slice tests Spring:
    • @WebMvcTest
    • @DataJpaTest
Ils sont: rapides, isolés et exécutés au build
Répartition recommandée
Couche Objectif Outils
Services Logique métier Mockito
Repositories Requêtes JPA @DataJpaTest + H2
Contrôleurs API HTTP @WebMvcTest + MockMvc

Configuration du plugin "Surefire" de Maven
<plugin>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>3.5.3</version>
    <configuration>
        <skipTests>${skipUnitTests}</skipTests>
    </configuration>
</plugin>

Organisation standard:

Tous les tests vont dans src/test/java/../../flashcards/, et respecte strictement la même arborescence de packages entre production et tests.

Spring Boot ajoute automatiquement JUnit et Mockito via la dépendance spring-boot-starter-test


Commandes de lancement
Localement:
./mvnw test
ou:
./mvnw clean verify

La commande verify déclenche l'ensemble du cycle qualité:
→ Les tests unitaires, les plugins d'analyse (Checkstyle, SpotBugs, JaCoCo…) ainsi que la génération des rapports

Ordre conseillé

Les tests de services en «vrai unitaire» visent à valider la logique métier d'une classe en isolation totale, sans dépendances réelles.

Pour atteindre cette isolation, les dépendances sont mockées afin de se concentrer uniquement sur le comportement de l'unité testée.

Pour tester les repositories sans charger tout le contexte Spring, on utilise @DataJpaTest.

Services: 3-5 tests par méthode critique
(cas nominal, not found, validation, edge cases)
Repositories (slice test):
1-2 tests par requête custom
Controllers (slice test web): 1 test par endpoint (GET/POST/PUT/DELETE)
Point de départ recommandé: la couche métier
Principe:
  • On teste uniquement la logique
  • On mock les repositories
  • Aucun contexte Spring n'est chargé
Structure: @Mock pour les dépendances, @InjectMocks pour les classe testée
Pattern: Given / When / Then
Avantages: Rapidité, isolation, Déterminisme
Détection rapide des régressions métier
L'exécution est ultra rapide
Tests de repositories (JPA slice)
Objectif:
  • Valider les requêtes dérivées
  • Tester les @Query
  • Vérifier les mappings
Approche: @DataJpaTest: Spring démarre un contexte JPA minimal avec la base H2 in-memory et les transactions en rollback automatiques
Workflow typique :
→ persister des entités
→ appeler la méthode repository
Tests de contrôleurs (Web slice)
Objectif:
  • Tester les endpoints HTTP
  • Valider le JSON
  • Vérifier les codes HTTP
Avec : MockMvc, et les services mockés via @MockBean, on teste:
Le routing, la validation, la sérialisation et les réponses HTTP, sans démarrer de serveur réel
En entreprise, cette approche couvre la majorité des besoins

Intégration dans le pipeline CI/CD
Les tests unitaires constituent le premier étage de la pyramide:
Unitaires >> Intégration >> E2E
Ils doivent être:
  • rapides (< 1 min)
  • systématiques
  • bloquants en cas d'échec
Exemple GitHub Actions
- name: Run Maven build + tests
  run: ./mvnw -B clean verify
Avec JaCoCo
- name: Run Maven clean verify (tests + coverage)
  run: ./mvnw -B clean verify jacoco:report

Gestion du profil de test
Important pour éviter les effets de bord
Toujours forcer @ActiveProfiles("test"), autrement Spring pourrait charger le fichier application.properties
Ce qui entraine des risques tels que: mauvaise base, mauvais port ou mauvais crédentials

Logs et debugging CI

Les rapports sont générés dans: target/surefire-reports/
Depuis GitHub Actions : allez dans "Actions", ouvrez le job depuis l'environnement voulu et consultez l'étape où les tests sont exécutés

Exemple: Depuis le job "Build and test", à l'étape "Run Maven clean test", utilisez la commande: run ./mvnw -B clean verify jacoco:report, ouvrez-la pour consulter les logs. Si l'artifact est uploadé, téléchargez le fichier "jacoco-report.xml" directement.

Stratégie prévue par environnement

Workflow Dev : Tests rapides, H2 ou PostgreSQL local, feedback immédiat.
Workflow Staging/Prod : Tests complets, vraie base PostgreSQL, couverture maximale.

Les points à améliorer progressivement sont: le seuil minimum de couverture et la quality gate bloquante.
Se référer à l'article Couverture de code avec JaCoCo pour avoir plus d'informations à ce sujet.


Dans l'article suivant, nous verrons comment sécuriser la qualité du code (formatage, analyse statique), avant d'intégrer ces contrôles dans un pipeline CI/CD.


Laissez-moi un commentaire

En postant un commentaire anonyme, vous adhérez automatiquement aux conditions d'utilisation du site.