Deno Test d’intégration

By | juin 10, 2021

Les tests sont une composante fondamentale de n’importe quelle application. Je suis un très grand fan du TDD. Dans cet article nous allons voir comment réaliser des tests avec Deno. Deno propose un environnement de test minimaliste mais permettant déjà de réaliser pas mal de chose. Si vous êtes habitué au Framework comme Jest ou Mocha, ce minimaliste peut être déroutant mais rien de rédhibitoire.

Prérequis

  • Deno installé
  • Oak le seul framework orienté API avec Drash en ce moment

Démonstration

Commençons par créer un fichier app.ts qui nous retournera un objet Application utilisable pour nos tests.

    import { Application, Router } from "https://deno.land/x/oak/mod.ts";
    import { UsersRoute } from "./users.route.ts";

    export class OakServer {

        private readonly hostname: string;
        private readonly port: number;
        private readonly app: Application;

        constructor(hostname: string, port: number) {
            this.hostname = hostname;
            this.port = port;
            const router = new Router();
            // Create the Oak Application
            this.app = new Application();
            // Create the User route and associate it with the Oak router
            new UsersRoute(router);
            // Associate the router with the application
            this.app.use(router.routes());
            this.app.use(router.allowedMethods());
        }

        async start(signal?: AbortSignal): Promise<void> {
            console.log("Starting server");
            let listenPromise: Promise<void>;
            if(signal) {
                listenPromise = this.app.listen({ hostname: this.hostname, port: this.port, signal });
                return listenPromise;
            } else {
                return await this.app.listen({ hostname: this.hostname, port: this.port });
            }
        }
    }

On définit une classe avec un constructeur prenant comme paramètre un hostnameet un port. On ajoute ensuite la route UsersRoute et on associe cette route avec notre router lui-même associé à notre application.

La méthode startpermet de démarrer notre application. Une petite subtilité ici. Par défaut la méthode listen retourne une promesse qui ne se résout que lorsque le serveur s’arrête. Cela convient très bien pour une utilisation standard. Mais pour nos tests, cela pose problème puisque nos tests situés après le lancement du serveur ne seront jamais exécutés.

La solution est d’utiliser la méthode listen prenant un paramètre un AbortSignal. Ce signal sera utilisé pour terminer le serveur une fois les tests d’intégration terminés.

La route user

Avant de voir notre test, voyons à quoi ressemble notre route users.route.ts.

import { Router } from "https://deno.land/x/oak/mod.ts";

export class UsersRoute {
  private readonly router: Router;
  public constructor(router: Router) {
     this.router = router;
     this.findAll();
     this.create();
     this.delete();
     this.find();
     this.update();
  }
  findAll(): void {
    this.router.get("/users", async (context) => {
      context.response.body = JSON.stringify({
         data: [{
             id: "1",
             name: "Bob"
         },{
             id: "2",
             name: "Alice"
         }]
      })
    });
  }

  create(): void {
    // create code
  }

  delete(): void {
     // delete code
  }

  find(): void {
     // find code
  }

  update(): void {
    // update codec
  }
}

Dans le constructeur de cette classe nous appelons les méthodes permettant d’associer des routes à notre router. Dans cet exemple nous associons la méthode GET('/users').

Si nous lançons notre serveur nous avons maintenant un serveur deno proposant une liste d’utilisateur sous le contexte /users.

Les tests d’intégration

On créer le fichier de test test/user.e2e.test.ts

import { OakServer } from '../app.ts';
import {
    assertEquals,
    fail,
} from "https://deno.land/std/testing/asserts.ts";
import axiosd from "https://deno.land/x/axiod/mod.ts";

const hostname = "localhost";
const port = 1447;
const httpUrl = `http://${hostname}:${port}`;

const abortController: AbortController;

async function startServer() {
    abortController = new AbortController();
    console.log("Starting test server");
    try {
        listenPromise = new OakServer(hostname, port).start(abortController.signal);
    } catch (err) {
        console.error(`Server can't start : ${err}`);
    }

}

function stopServer() {
    abortController.abort();
    await listenPromise;
    console.log("server stop");
}

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.