Passer au contenu

Tests automatisés avec NestJS

Automatiser les tests est considéré comme une partie essentielle de tout développement logiciel sérieux. L’automatisation facilite la répétition des tests individuels ou des suites de tests rapidement et facilement pendant le développement. Cela aide à garantir que les versions respectent les objectifs de qualité et de performance. L’automatisation augmente la couverture et fournit un retour d’information plus rapide aux développeurs. Elle augmente à la fois la productivité des développeurs individuels et garantit que les tests sont exécutés à des moments clés du cycle de vie du développement, tels que l’enregistrement dans le contrôle de code source, l’intégration des fonctionnalités et la publication des versions.

De tels tests couvrent souvent une variété de types, y compris les tests unitaires, les tests de bout en bout (e2e), les tests d’intégration, etc. Bien que les avantages soient indiscutables, il peut être fastidieux de les mettre en place. Nest s’efforce de promouvoir les meilleures pratiques de développement, y compris des tests efficaces, il inclut donc des fonctionnalités telles que les suivantes pour aider les développeurs et les équipes à construire et automatiser des tests :

  • génère automatiquement des tests unitaires par défaut pour les composants et des tests e2e pour les applications
  • fournit des outils par défaut (comme un exécuteur de tests construit sur un chargeur de module/application isolé)
  • fournit une intégration avec Jest et Supertest par défaut, tout en restant agnostique vis-à-vis des outils de test
  • rend le système d’injection de dépendances de Nest disponible dans l’environnement de test pour faciliter le moquage de composants

Comme mentionné, vous pouvez utiliser n’importe quel cadre de test que vous aimez, car Nest ne force aucun outil spécifique. Remplacez simplement les éléments nécessaires (comme l’exécuteur de tests), et vous bénéficierez toujours des avantages des installations de tests prêtes à l’emploi de Nest.

Installation

Pour commencer, installez d’abord le paquet requis :

Fenêtre de terminal
$ npm i --save-dev @nestjs/testing

Tests unitaires

Dans l’exemple suivant, nous testons deux classes : CatsController et CatsService. Comme mentionné, Jest est fourni comme cadre de test par défaut. Il sert d’exécuteur de tests et fournit également des fonctions d’assertion et des utilitaires de doubles de test qui aident avec le moquage, l’espionnage, etc. Dans le test basique suivant, nous instancions manuellement ces classes et nous assurons que le contrôleur et le service remplissent leur contrat API.

cats.controller.spec.ts
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
describe('CatsController', () => {
let catsController: CatsController;
let catsService: CatsService;
beforeEach(() => {
catsService = new CatsService();
catsController = new CatsController(catsService);
});
describe('findAll', () => {
it('should return an array of cats', async () => {
const result = ['test'];
jest.spyOn(catsService, 'findAll').mockImplementation(() => result);
expect(await catsController.findAll()).toBe(result);
});
});
});

Parce que l’exemple ci-dessus est trivial, nous ne testons rien de spécifique à Nest. En effet, nous n’utilisons même pas l’injection de dépendances (remarquez que nous passons une instance de CatsService à notre catsController). Cette forme de test - où nous instancions manuellement les classes testées - est souvent appelée test isolé car elle est indépendante du framework. Introduisons quelques fonctionnalités plus avancées qui vous aident à tester des applications qui utilisent davantage les fonctionnalités de Nest.

Utilitaires de test

Le paquet @nestjs/testing fournit un ensemble d’utilitaires qui permettent un processus de test plus robuste. Réécrivons l’exemple précédent en utilisant la classe intégrée Test :

cats.controller.spec.ts
import { Test } from '@nestjs/testing';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
describe('CatsController', () => {
let catsController: CatsController;
let catsService: CatsService;
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
controllers: [CatsController],
providers: [CatsService],
}).compile();
catsService = moduleRef.get<CatsService>(CatsService);
catsController = moduleRef.get<CatsController>(CatsController);
});
describe('findAll', () => {
it('should return an array of cats', async () => {
const result = ['test'];
jest.spyOn(catsService, 'findAll').mockImplementation(() => result);
expect(await catsController.findAll()).toBe(result);
});
});
});