← Voir tous les articlesGrégory TAUDINGrégory TAUDIN - 9 juin 2022

NestJS : Tests unitaires et E2E avec Jest

NestJS logo

Notre API est fonctionnelle mais nous n'avons implémenté aucun test pour valider son fonctionnement et ainsi éviter de futures régressions. NestJS nous facilite le travail et possède, en son sein, tout le nécessaire pour réaliser des tests avec JEST, que ce soient des tests unitaires, d'intégration ou encore E2E (End to End).

Lorsqu'on utilise la CLI pour générer les éléments que nous allons utiliser, NestJS génère toujours les fichiers tests associés aux types demandés. Par exemple, nous avons généré le service « InventoryService », vous aurez remarqué que le fichier test associé est bien présent dans la solution.

Nous allons donc commencer par tester la couche service, ensuite les contrôleurs et nous finirons par la couche E2E.

Les tests de la couche service doivent se concentrer sur les interactions avec le repository « TypeOrm ». Nous devons donc mocker le repository « InventoryItem ».

NestJS nous livre un objet directement à utiliser au travers de l'importation suivante :

import { getRepositoryToken } from '@nestjs/typeorm';

La méthode « getRepositoryToken » nous permet de récupérer un faux repository, mais qui est néanmoins, correctement typé et simule l'ensemble des méthodes qui sont disponibles au sein de la classe repository. Nous allons créer une fausse collection d'objets d'inventaire qui nous permettra de simuler les retours de données et ainsi finaliser l'ensemble des besoins que nous avons pour réaliser les tests.

Github code

Les deux tests qui sont développés testent les cas nominaux et un cas d'erreur qui peut se produire dans les méthodes « findAll » et « create ».

Passons aux contrôleurs :

Les tests sur les contrôleurs doivent se concentrer sur les appels du service « InventoryService ».

Il nous faut donc mocker le service. Pour cela nous allons utiliser un provider spécifique pour simuler notre service.

Github code

Dans la couche « reader », nous avons besoin de tester uniquement la méthode « findAll » tandis que la couche « writer » se chargera du « create », « update », et « delete ». Ils partageront donc le même mock de service.

Pas de difficulté particulière à implémenter les tests une fois que nous avons le service mocké.

Finalement passons aux tests E2E :

Le but étant vraiment de tester les appels d'API, il faut mettre en place de nouveaux éléments de configuration :

Il faut installer la librairie suivante :

> npm install @nestjs/conf

Ce module permet d'utiliser et paramétrer la configuration de NestJS. Il faut avant tout rajouter une importation au niveau de notre librairie pour prendre en compte le nouveau module :

ConfigModule.forRoot({ isGlobal: true }),

A la racine de la solution, créons un fichier « .env », ce sera notre configuration de base. Rajoutons 2 clés, une pour le nom de la base d'utilisation et une autre pour le nom de notre base de tests :

Notre fichier est prêt. Ensuite nous avons à modifier l'importation de « TypeOrm ».

Dans le fichier « shared.module.ts » de la librairie, nous allons utiliser une « factory » de construction et lui passer le module « configModule » ainsi que le service de configuration « configService » pour récupérer nos 2 clés de configuration. NestJS se charge ainsi de faire le lien entre la configuration de NodeJS au travers du fichier « .env » et notre couche service.

Github code

Nous sommes donc capables de passer d'une base à l'autre pour notre dev et nos tests grâce à la variable d'environnement « process.env.NODE_ENV ».

Retournons dans nos fichiers de tests E2E (dossier « test » à la racine de chaque app). La première étape est de rajouter une section « moduleNameMapper » dans le fichier « jest-e2e.json » pour paramétrer le chemin de la librairie, sinon vous aurez une erreur sur l'importation de la librairie dans chaque application : « reader » et « writer ».

Github code
Github code

Notez que la création de la base de données de test et l'insertion de données avec une requête SQL : avec cette méthode, vous ajoutez un ensemble complet de données pour créer un véritable schéma de test. La base de données est créée à chaque lancement des tests E2E. Remarquez cette ligne :

request(app.getHttpServer()).get('/inventory').

Cette fonction asynchrone nous permet d'interroger notre base de données de test et renvoie la réponse HTTP : nous pouvons donc valider les données renvoyées et terminer nos tests E2E.Pour le "writer" l'approche est la même mais nous utiliserons POST, PUT et DELETE pour tester les différentes parties de l'API.

Github code

Mission complete!

Nos tests sont implémentés, nous pouvons penser à la prochaine étape : les objets DTO avec Automapper.