Mettre en place Jest pour vos tests unitaires Angular

Par défaut, les applications Angular utilisent Karma et Jasmine pour les tests unitaires. Dans cet article, nous allons voir comment remplacer ces outils par le framework de test Jest.

1. Installer les dépendances

Pour installer les dépendances requises, lancer la commande suivante dans un terminal :

npm install jest jest-preset-angular @types/jest --save-dev

Si vous utilisez Yarn, la commande à lancer est :

yarn add --dev jest jest-preset-angular @types/jest

Jest

Jest est un framework de test complet créé par Facebook et qui est très populaire dans l’écosystème React. Il vient avec tout le bagage nécessaire pour réaliser des tests unitaires pour nos applications JavaScript. Il comprend :

  • d’importantes capacités de mock,
  • une bibliothèque d’assertion intégrée,
  • un outil de code coverage intégré,
  • JSDOM, une librairie émulant le navigateur.
JSDOM va nous permettre d'exécuter nos tests unitaires sur nos serveurs d'intégration continue sans configuration supplémentaire.

Je préfère Jest à Karma et Jasmine, car Jest offre une bien meilleure expérience développeur. Il est :

  • plus rapide que Karma avec une parallélisation de l’exécution des tests,
  • très bien documenté avec une large communauté derrière,
  • plus intelligent que Karma (en ne relançant que les tests affectés par exemple),
  • un toolkit complet pour les tests unitaires,
  • headless par défaut grâce à la librairie JSDOM.

Les déclarations de types pour Jest

Le paquet @types/jest contient les déclarations de types qui vont permettre à TypeScript d’effectuer la vérification du typage statique de notre code.

Jest Preset Angular

Le paquet jest-preset-angular est l’outil qui permet à Jest de comprendre notre code Angular. C’est ce qui rend possible l’exécution des tests unitaires de notre application Angular via Jest. Il inclut :

  • ts-jest, une librairie qui permet à Jest de transpiler à la volée notre code TypeScript avant de lancer les tests,
  • des sérialiseurs pour permettre la réalisation de tests par comparaison de snapshots,
  • des transformateurs AST qui suppriment le CSS de notre composant et qui “inline” le template HTML de nos composants Angular, les rendant ainsi compatibles avec JSDOM.

2. Configurer Jest

Supposons que nous ayons généré une application Angular appelée my-app avec la commande suivante :

ng new my-app

Créer le fichier de configuration de Jest

Créez le fichier jest.config.js à la racine de votre projet avec le contenu suivant :

const { pathsToModuleNameMapper } = require('ts-jest/utils');
const { compilerOptions } = require('./tsconfig');
module.exports = {
preset: 'jest-preset-angular',
roots: ['<rootDir>/src/'],
testMatch: ['**/+(*.)+(spec).+(ts|js)'],
setupFilesAfterEnv: ['<rootDir>/src/test.ts'],
collectCoverage: true,
coverageReporters: ['html'],
coverageDirectory: 'coverage/my-app',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths || {}, {
prefix: '<rootDir>/',
}),
};

Le fichier jest.config.js contient la configuration de Jest. Avec cette configuration, Jest va :

  • prendre en comprendre tous les fichiers .spec.ts se trouvant dans le dossier src de notre projet,
  • lire notre fichier de configuration de TypeScript tsconfig.json à la recherche d’alias pour qu’on puisse utiliser les alias dans nos tests,
  • transpiler à la volée notre code TypeScript avant de lancer les tests,
  • collecter les informations sur la couverture de code et les écrire dans le dossier coverage/my-app.

Mettre à jour le contenu du fichier src/test.ts

Ouvrez le fichier src/test.ts et remplacer son contenu par :

import 'jest-preset-angular';
Object.defineProperty(window, 'CSS', { value: null });
Object.defineProperty(window, 'getComputedStyle', {
value: () => {
return {
display: 'none',
appearance: ['-webkit-appearance'],
};
},
});
Object.defineProperty(document, 'doctype', {
value: '<!DOCTYPE html>',
});
Object.defineProperty(document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true,
};
},
});

Ce bout de code fait deux choses :

  1. Il importe le module JavaScript jest-preset-angular pour mettre en place notre environnement de test Angular.
  2. Il “mock” certaines propriétés et fonctions de l’object global window pour s’assurer que nos tests peuvent bien tourner dans un environnement JSDOM.

Mettre à jour la configuration TypeScript pour les tests

Ouvrez le fichier tsconfig.spec.json et mettez à jour son contenu :

{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jest", // 1
"node"
],
"esModuleInterop": true, // 2
"emitDecoratorMetadata": true // 3
},
"files": ["src/test.ts", "src/polyfills.ts"],
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}

Ces changements ont pour effets :

  1. d’instruire le compilateur TypeScript de prendre en compte le fichier de déclarations de types de Jest,
  2. d’activer l’option esModuleInterop du compilateur TypeScript sinon Jest va produire beaucoup d’avertissements dans la console,
  3. d’activer l’option emitDecoratorMetadata du compilateur TypeScript sinon l’injection de dépendance d’Angular ne fonctionnera pas avec Jest.

3. Lancer les tests

Vous pouvez maintenant lancer les tests unitaires grâce à la commande suivante :

npx jest

npx

4. Enlever Karma

Nous pouvons maintenant tranquillement enlever Karma de notre projet

Désinstaller Karma

Pour supprimer les dépendances vers Karma et son écosystème, lancer la commande suivante dans un terminal :

npm uninstall karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter

Si vous utilisez Yarn, la commande à lancer est :

yarn remove karma karma-chrome-launcher karma-coverage-istanbul-reporter karma-jasmine karma-jasmine-html-reporter

Supprimer le fichier de configuration de Karma

Nous pouvons maintenant supprimer le fichier de configuration de Karma :

rm karma.conf.js

Supprimer le target “test” du ficher “angular.json”

Au lieu de ng test, nous allons maintenant exécuter npx jest pour lancer nos tests unitaires. Par conséquent, le target test à l’intérieur du fichier angular.json devient inutile. Vous pouvez donc supprimer la section projects.my-app.architect.testdu fichier angular.json :

{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"my-app": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": { /* config du target build */ },
"serve": { /* config du target serve */ },
- "test": {
- "builder": "@angular-devkit/build-angular:karma",
- "options": {
- "main": "src/test.ts",
- "polyfills": "src/polyfills.ts",
- "tsConfig": "tsconfig.spec.json",
- "karmaConfig": "karma.conf.js",
- "assets": [
- "src/favicon.ico",
- "src/assets"
- ],
- "styles": [
- "src/styles.css"
- ],
- "scripts": []
- }
- },
"lint": { /* config du target lint*/ },
"e2e": { /* config du target e2e */ }
}
}},
"defaultProject": "my-app"
}

Conclusion

Dans cet article, nous avons vu comment nous pouvons mettre en place Jest pour nos tests unitaires. Cela peut certainement être automatisé à l’aide de schematics Angular, mais ce n’est pas si difficile à faire manuellement.

Vous pouvez par exemple ajouter Jest à votre projet Angular en utilisant les schematics de Briebug en exécutant la commande suivante:

ng add @briebug/jest-schematic

Vous pourrez trouver Le code source complet de cet article dans ce dépôt Github.


Vous aimez ce blog ?
Suivez-moi sur Twitter pour plus de contenu !

Rejoignez la newsletter pour du contenu de grande qualité dans votre boite mail

Pas de spam. Que du contenu de qualité.