Série découverte, épisode 03 : Tester une API REST avec Spring-boot

Jeremie Guidoux
22/05/2018

Previously, in the découverte series

Dans l’article précédent, on a vu comment créer une API REST simple avec Spring-boot from scratch. L’objectif de cet article est de tester notre première API REST grâce aux outils que nous donne Spring-boot.

Mais tout d’abord, Pourquoi tester ?

On pourrait simplement se dire : « Mais on a déjà testé l’application dans l’article précédent, pourquoi s’embêter ? ». Effectivement, dans cet article, on avait exécuté notre application, puis vérifié, grâce à un navigateur web, que son unique API REST avait le comportement désiré.

Ceci était un test manuel. Je ne vais pas aller trop loin dans la philosophie du test aujourd’hui. On verra cela probablement plus tard. Pour le moment, posons-nous juste la question suivante :

  • La fonctionnalité ‘hello-world’ fonctionnera-t-elle toujours demain ? Ou dans un mois ?

En effet, chaque modification du code peut entraîner des régressions. Plus l’application s’étoffe, vieillit, avec potentiellement une équipe importante travaillant dessus, plus le risque de régression est grand, voir… inévitable.

Bon, on peut se dire :

Et que se passe-t-il quand le nombre de test à effectuer est de l’ordre de la centaine ? Du millier ? Voir beaucoup plus. Dois-je tous les refaire ? Quand ? À chaque changement ? Release ? Une plainte d’un client ? Comment s’assurer que je n’ai oublié aucun test ? Combien de temps cela va-t-il me prendre de tout tester ? Combien cela va coûter à l’entreprise ?

Il faut également savoir que, plus un bug, ou une correction nécessaire intervient tard, plus elle coûte cher. Voire très cher. Je vous conseille de lire cet article qui présente les coûts possibles d’un bug. Vous pouvez également lire cet article qui présente le coût des bugs dans le domaine hospitalier français. Les articles intéressants sur ce sujet sur le net font légion.

Au final, et très rapidement, les tests manuels deviennent invivables. Reste alors la solution : automatiser les tests.

Mise en place du test

Il existe un grand nombre de technologies de tests. Pour de moment, je vais me contenter de junit4 avec Spring-boot-test. Mais très rapidement on va jeter un œil sur des outils bien plus puissants. On a la chance de nos jours d’avoir des outils de tests très puissant qui rendent l’écriture de tests automatisés lisible, puissants et simple à écrire.

Avec Gradle les tests s’écrivent dans le dossier src/test/java et en général dans le package associé au code qu’on souhaite tester. Commençons donc par nous poser la question de ce qu’on désire tester.

On veut tester que la requête HTTP : GET http://localhost:8080/hello nous renvoie bien la chaîne de caractère “Hello World”.

C’est notre Controller HomeController qui produit ce résultat, c’est donc lui qu’on va tester.

On va donc créer une class HomeControllerTest dans le package fr.slickteam.decouverte.gog.controller

On va ensuite ajouter Spring-boot-test à notre test. Mais avant, il faut s’assurer que notre projet à bien spring-boot-test en dépendances. Gradle (tout comme Maven) est capable d’ajouter des dépendances depuis le net au classpath du projet.

Ajouter la dépendance spring-boot-test

La dépendance spring-boot pour écrire des tests est :

org.springframework.boot:spring-boot-starter-test

Étant donné, qu’on avait utilisé le site http://start.spring.io/ dans l’article précédent pour générer notre projet, Spring a automatiquement ajouté cette dépendance dans votre projet ( Comme quoi, Spring considère aussi que tester c’est important 😃).

Si ce n’est pas le cas chez vous, ajoutez cette dépendance en scope testCompile. L’article découverte-01 détaille la façon de faire.

Écriture du test

Pour tester une application, il nous faut lancer l’application. On verra plus tard qu’on peut optimiser cela, voire complètement s’en passer, mais restons simple pour le moment 😃.

  1. Pour commencer : créez une classe HomeControllerTest dans le dossier src/test/java et dans le package fr.slickteam.decouverte.gog.controller

L’initialisation du contexte Spring peut se faire facilement via des annotations.

2. Ajoutez les annotations suivantes :

(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT) permet de lancer le serveur pour chaque test sur un port différent.

Ensuite on va tester notre contrôleur pour vérifier qu’il retourne bien “hello world” quand il reçoit une requête HTTP GET /hello

3. Créez une méthode returnhelloworldwhergethello annotée @org.junit.Test

@Testpublic void returnhelloworldwhergethello() {}

Maintenant, on va tenter d’appeler notre contrôleur avec une requête HTTP. Pour cela, on va utiliser la classe TestRestTemplate que permet de simuler le comportement d’une requête HTTP.

4. Ajoutez en attribut org.springframework.boot.test.web.client.TestRestTemplate à notre classe de test, et annotez-la avec @org.springframework.beans.factory.annotation.Autowired. Cette annotation permet à Spring d’instancier automatiquement l’objet TestRestTemplate

@Autowiredprivate TestRestTemplate restTemplate;

La classe TestRestTemplate possède une méthode getForObject() qui va nous intéresser. Cette méthode, à partir d’une URL permet de récupérer le “body” de la requête HTTP réponse. Dans notre cas la réponse doit contenir un body de type String contenant la chaîne de caractère “Hello World”.

5. Ajoutez la ligne suivante pour avoir ce comportement :

String body = this.restTemplate.getForObject("/hello", String.class);

Il ne reste plus qu’à vérifier le contenu de ce body. Pour cela, on va utiliser AssertJ que spring-boot-test nous à gentiment (et généreusement ramener 😃). AssertJ permet d’écrire intuitivement des assertions puissantes.

6. Ajoutez l’assertion suivante :

assertThat(body).isEqualTo("Hello World");

7. Vous pouvez maintenant lancer le test. Vous pouvez le faire avec votre IDE, mais vous pouvez également le faire avec Gradle.

Exécutez l’une des 2 commandes suivante :

  • ./gradlew test

ou bien

  • ./gradlew build

Vous devriez obtenir ce résultat.

7. Changez les valeurs afin de faire échouer le test et relancez-le. Vous pouvez également vérifier le rapport HTML généré. Ce rapport se trouve à cet emplacement dans votre projet :

  • build/reports/tests/test/index.html

N’hésitez pas à lire l’article sur Gradle pour avoir plus d’information.

Voici le fichier complet :

En conclusion

On a pu écrire notre premier test pour notre jeu guild-of-geek. Ce test, est un test d’intégration qui lance le serveur, exécute une requête HTTP et vérifie le contenu de la requête HTTP réponse. À partir de là, vous devriez être capable de tester une API REST Simple. On verra à l’avenir comment on peut tester une API REST qui retourne un objet JSON et non une simple String. Mais vous le verrez, l’essentiel est là 😃 !

Les sources GIT

Les sources se trouvent sur github : https://github.com/Slickteam/Guild-of-Geeks.

Les tags sont :

  • decouverte03start correspond à l’état initial du projet

  • decouverte03solution pour le résultat final

In the next épisode

Dans le prochain article, je vais vous présenter un autre outil de test. Un outil que j’apprécie tout particulièrement : Spock

Slickteam