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 :
$ 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.
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
:
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); }); });});