Préférez-vous découvrir une fondation défectueuse lorsque vous posez le toit, ou avant même d'avoir posé la première brique ? C'est en résumé ce qu'est le test unitaire.

  • 🐛 Élimination des bugs : Attrapez ces bugs embêtants tôt, avant qu'ils ne deviennent des problèmes monstrueux.
  • 🔧 Refactorisation sans crainte : Modifiez votre code en toute confiance, sachant que vos tests vous soutiennent.
  • 💎 Amélioration de la qualité du code : Écrivez un code plus propre et modulaire que même votre futur vous remerciera.

Et quand il s'agit de tester des microservices avec Quarkus ? Le test unitaire devient votre cape de super-héros. Il vous aide à isoler les composants, en s'assurant que chaque pièce de votre puzzle microservice s'emboîte parfaitement avant d'assembler le tout.

JUnit 5

JUnit 5 n'est pas juste une mise à jour ; c'est une refonte complète qui rend les tests en Java moins fastidieux et plus puissants. Découvrons quelques-unes des nouvelles fonctionnalités qui faciliteront votre vie de testeur :

Quoi de neuf et brillant ?

  • @BeforeEach et @AfterEach : Exit les anciens (@Before et @After), place aux nouveaux ! Ces annotations simplifient la configuration et le démontage de vos tests.
  • @Nested : Regroupez les tests liés comme un pro. C'est comme organiser votre tiroir à chaussettes, mais pour le code.
  • @TestFactory : Des tests dynamiques qui s'adaptent et évoluent. C'est le test qui évolue avec votre code !

Voyons un test simple en action :


@Test
void additionShouldWorkLikeInElementarySchool() {
    int result = 2 + 2;
    assertEquals(4, result, "On dirait que les maths sont cassées. Il est temps de paniquer !");
}

Simple, non ? Mais ne vous laissez pas tromper par sa simplicité. Ce petit test assure que votre arithmétique de base ne déraille pas.

Préparer l'arène de test dans Quarkus

Maintenant, préparons notre projet Quarkus pour une action de test sérieuse. Tout d'abord, nous devons inviter JUnit 5 à la fête. Ajoutez ceci à votre pom.xml :


<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-junit5</artifactId>
    <scope>test</scope>
</dependency>

Avec cela en place, voyons comment faire en sorte que JUnit 5 et Quarkus fonctionnent bien ensemble :


@QuarkusTest
public class MyAmazingServiceTest {
    @Inject
    MyAmazingService service;

    @Test
    void testServiceLogic() {
        assertTrue(service.isAwesome("Quarkus"), "Notre service devrait reconnaître la grandeur de Quarkus !");
    }
}

L'annotation @QuarkusTest est comme une baguette magique qui configure l'environnement de test Quarkus. Elle garantit que vos tests s'exécutent dans un mini-monde Quarkus, avec injection de dépendances et toutes les fonctionnalités de Quarkus.

Test des API REST : Parce que les API doivent être tranquilles

Tester les API REST est là où les choses deviennent vraiment amusantes. Nous allons utiliser RestAssured, qui rend le test des API aussi simple qu'une promenade dans le parc. Voici un exemple savoureux :


@QuarkusTest
public class SuperheroResourceTest {
    @Test
    void testGetSuperhero() {
        given()
          .when().get("/superhero/batman")
          .then()
             .statusCode(200)
             .body("name", equalTo("Bruce Wayne"))
             .body("superpower", equalTo("Être riche"));
    }
}

Ce test vérifie si notre point de terminaison /superhero renvoie correctement la véritable identité et le superpouvoir de Batman. Rappelez-vous, avec un grand pouvoir vient une grande testabilité !

Conseils de pro pour le test des API :

  • Testez différentes méthodes HTTP (GET, POST, PUT, DELETE) pour assurer une couverture complète.
  • N'oubliez pas de tester les scénarios d'erreur. Que se passe-t-il lorsque quelqu'un demande un super-héros qui n'existe pas ?
  • Utilisez des tests paramétrés pour vérifier plusieurs entrées sans dupliquer le code.

Test de la couche de service : Là où la magie opère

La couche de service est là où se trouve la plupart de votre logique métier, il est donc crucial de la tester minutieusement. Voici où Mockito est utile :


@QuarkusTest
public class SuperheroServiceTest {
    @InjectMock
    SuperheroRepository mockRepository;

    @Inject
    SuperheroService service;

    @Test
    void testFindSuperhero() {
        Superhero batman = new Superhero("Batman", "Être riche");
        when(mockRepository.findByName("Batman")).thenReturn(Optional.of(batman));

        Optional<Superhero> result = service.findSuperhero("Batman");
        assertTrue(result.isPresent());
        assertEquals("Être riche", result.get().getSuperpower());
    }
}

Ici, nous simulons le dépôt pour isoler notre test de service. De cette façon, nous sommes sûrs de tester la logique du service, pas l'interaction avec la base de données.

Éviter la dépendance à la base de données

Rappelez-vous, les tests unitaires doivent être rapides et indépendants. Évitez d'accéder à la base de données dans vos tests unitaires. Réservez cela pour les tests d'intégration. Votre futur vous (et votre pipeline CI/CD) vous remerciera.

Test du dépôt : Gestion des bases de données bien faite

En ce qui concerne le test du dépôt, nous voulons nous assurer que notre couche d'accès aux données fonctionne correctement sans perturber notre base de données réelle. Entrez @QuarkusTestResource :


@QuarkusTest
@QuarkusTestResource(H2DatabaseTestResource.class)
public class SuperheroRepositoryTest {
    @Inject
    SuperheroRepository repository;

    @Test
    void testSaveAndRetrieveSuperhero() {
        Superhero wonderWoman = new Superhero("Wonder Woman", "Force surhumaine");
        repository.persist(wonderWoman);

        Superhero retrieved = repository.findById(wonderWoman.getId()).orElseThrow();
        assertEquals("Wonder Woman", retrieved.getName());
        assertEquals("Force surhumaine", retrieved.getSuperpower());
    }
}

Cette configuration utilise une base de données H2 en mémoire pour les tests, garantissant que vos tests sont isolés et reproductibles.

Meilleures pratiques : Les choses à faire et à ne pas faire en matière de tests unitaires

À faire :

  • Gardez vos tests courts et ciblés. Une bonne règle est un test, une assertion.
  • Utilisez des noms de tests significatifs. test1() ne vous dit rien, mais testSuperheroCreationWithValidInput() en dit long.
  • Testez les cas limites. Que se passe-t-il lorsque votre méthode reçoit null, une chaîne vide ou un nombre négatif ?

À ne pas faire :

  • Ne testez pas le code trivial. Les getters et setters n'ont généralement pas besoin de tests à moins qu'ils ne contiennent de la logique.
  • Évitez l'interdépendance des tests. Chaque test doit pouvoir s'exécuter indépendamment.
  • Ne pas ignorer les tests échoués. Un test échoué est comme un voyant moteur - l'ignorer à vos risques et périls !

Conclusion : La puissance des tests unitaires libérée

Et voilà, mesdames et messieurs ! Nous avons parcouru le monde de JUnit 5 et Quarkus, armés du savoir pour écrire des tests qui feraient même hocher la tête d'approbation au critique de code le plus sévère. Rappelez-vous, de bons tests sont comme de bons amis - ils vous disent la vérité, même quand ce n'est pas ce que vous voulez entendre.

En adoptant les tests unitaires, vous n'écrivez pas seulement un meilleur code ; vous construisez un filet de sécurité qui vous permet de coder en toute confiance. Alors allez-y, testez avec enthousiasme, et que votre build soit toujours vert !

"Le seul code vraiment sans bug est celui qui n'existe pas. Pour tout le reste, il y a les tests unitaires." - Développeur anonyme qui en a vu des choses

Bon test, et que votre code soit toujours sans bug !