Tester une Java Google Cloud Function
Jusqu’il y a peu de temps, tester une Google Cloud Function écrite en Java pouvait se faire via l’invoker fournit par le SDK des Google Cloud Functions mais pas via un test unitaire. Mais cela à changé récemment !
Prenons comme exemple la fonction HTTP suivante :
public class HelloHttpFunction implements HttpFunction { @Override public void service(HttpRequest httpRequest, HttpResponse httpResponse) throws Exception { Writer writer = httpResponse.getWriter(); writer.write("Hello World"); } }
Après packaging de celle-ci dans un über JAR, nous pouvons télécharger l’invoker Google Cloud function via la commande Maven suivante :
mvn dependency:copy \ -Dartifact='com.google.cloud.functions.invoker:java-function-invoker:1.1.1' \ -DoutputDirectory=.
Puis l’utiliser pour démarrer la fonction en local :
java -jar java-function-invoker-1.1.1.jar \ --classpath target/hello-world.jar \ --target org.example.HelloHttpFunction
Notre fonction est alors testable sur le port 8080.
Hélas, ceci n’est pas pratique dans une optique d’intégration continue où nous voudrions exécuter des tests automatisés avec JUnit par exemple.
Heureusement, l’invoker de fonction est un projet Open Source de Google et votre serviteur a proposé une PR pour permettre l’utilisation de celui-ci via des tests automatisés en proposant une méthode stop qui était manquante.
En utilisant sa dernière version, nous pouvons ajouter l’invoker en dépendance Maven de notre projet pour l’utiliser dans un test unitaire.
<dependency> <groupid>com.google.cloud.functions.invoker</groupid> <artifactid>java-function-invoker</artifactid> <version>1.1.1</version> <scope>test</scope> </dependency>
Nous pouvons alors créer des tests JUnit.
Par exemple pour notre fonction HTTP HelloHttpFunction
nous aurons le test suivant :
class HttpFunctionTestCase { @Test public void test() throws Exception { // start the invoker without joining to avoid blocking the thread Invoker invoker = new Invoker( 8081, "org.example.HelloHttpFunction", "http", Thread.currentThread().getContextClassLoader()); invoker.startTestServer(); // test the function using REST-assured when() .get("http://localhost:8081") .then() .statusCode(200) .body(is("Hello World!")); // stop the invoker invoker.stopServer(); } }
Le framework REST-assured est utilisé ici pour faciliter l’écriture de test HTTP.
Le troisième paramètre à passer lors de l’instanciation de l’invoker est le type de fonction à tester, tous les types de fonction sont supportés :
- http : pour les fonctions HTTP;
- event : pour les fonctions backgound;
- cloudevent : pour les fonctions Cloud Events.
Pour tester une fonction background qui réagit à un événement Cloud Storage, on va devoir envoyer un événement au format JSON via un POST HTTP sur l’URL de l’invoker. Nous pouvons utiliser REST-assured pour cela comme nous avons fait pour une fonction HTTP.
class BackgroundStorageFunctionTestCase { @Test public void test() throws Exception { // start the invoker without joining to avoid blocking the thread Invoker invoker = new Invoker( 8081, "org.example.BackgroundStorageFunction", "event", Thread.currentThread().getContextClassLoader()); invoker.startTestServer(); // test the function using REST-assured given() .body("{\"data\":{\"name\":\"hello.txt\"}}") .when() .post("http://localhost:8081") .then() .statusCode(200); // stop the invoker invoker.stopServer(); }
En conclusion, grâce à la version 1.1.1 de l’invoker de fonction Goole Cloud, nous pouvons tester nos fonctions automatiquement avec JUnit5, et s’assurer de leur qualité et leur non-régression fonctionnelle dans un workflow de CI.