Appearance
Tester avec Jest dans Angular
Vous voulez des tests plus rapides et plus simples dans votre application Angular ? Jest est la solution ! Ce framework de test moderne remplace avantageusement Karma et Jasmine par défaut d'Angular.
Dans ce tutoriel, nous allons voir comment migrer de Karma/Jasmine vers Jest pour profiter de ses avantages : tests plus rapides, meilleure intégration avec les outils modernes et une syntaxe plus claire.
WARNING
Jest n'est pas le framework de test officiel d'Angular. Attention, cela peut plus fastidieux à configurer et à utiliser.
Configuration de Jest avec Angular
Étape 1 : Installation des dépendances
Commençons par installer Jest et ses dépendances spécifiques à Angular :
bash
npm install -D jest jest-preset-angular @types/jest jest-environment-jsdom jsdom
Puis désinstallons Karma et Jasmine si ils sont présents :
bash
npm remove karma karma-chrome-launcher karma-jasmine karma-coverage karma-jasmine-html-reporter jasmine-core @types/jasmine
Configuration recommandée
Ces paquets sont les versions recommandées par jest-preset-angular
, le preset officiel pour Angular.
Étape 2 : Configuration Jest
Créons le fichier de configuration Jest à la racine du projet :
typescript
// jest.config.ts
const { createCjsPreset } = require('jest-preset-angular/presets');
/** @type {import('jest').Config} */
module.exports = {
...createCjsPreset(),
testEnvironment: 'jsdom',
setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
testPathIgnorePatterns: [
'<rootDir>/node_modules/',
'<rootDir>/dist/',
'<rootDir>/src/test.ts', // fichier Karma par défaut
],
};
export default config;
Cette configuration utilise le preset CommonJS d'Angular et configure l'environnement DOM pour les tests.
Mettez aussi "type": "module" dans le fichier package.json
Étape 3 : Fichier de setup
Créons le fichier setup-jest.ts
à la racine pour initialiser l'environnement de test :
typescript
// setup-jest.ts
import { setupZoneTestEnv } from 'jest-preset-angular/setup-env/zone';
// Initialise l'environnement Zone.js pour les tests Angular
setupZoneTestEnv();
Ce fichier configure Zone.js, nécessaire pour que les tests Angular fonctionnent correctement.
Étape 4 : Configuration TypeScript
Mettons à jour tsconfig.spec.json
pour Jest :
json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"types": ["jest"]
},
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}
Étape 5 : Scripts NPM
Modifions les scripts dans package.json
:
json
{
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:coverage": "jest --coverage"
}
}
Nettoyage Angular CLI
N'oubliez pas de supprimer ou vider la cible test
basée sur Karma dans angular.json
si vous ne l'utilisez plus.
Écrire des tests avec Jest et Angular
Maintenant que Jest est configuré, voyons les fonctionnalités spécifiques que Jest offre par rapport à Jasmine.
Fonctionnalités Jest vs Jasmine
Jest apporte de nombreuses améliorations par rapport à Jasmine. Voici les principales différences :
Jest.spyOn vs Jasmine.createSpy
Jest offre une syntaxe plus simple pour créer des espions :
typescript
// Avec Jasmine
const spy = jasmine.createSpy('methodName');
spy.and.returnValue(mockValue);
// Avec Jest - Plus simple et expressif
const spy = jest.spyOn(service, 'methodName');
spy.mockReturnValue(mockValue);
Mock automatique avec jest.mock()
Jest peut automatiquement mocker des modules entiers :
typescript
// Mock automatique d'un service
jest.mock('./user.service', () => ({
UserService: jest.fn().mockImplementation(() => ({
getUsers: jest.fn().mockReturnValue([]),
addUser: jest.fn()
}))
}));
Snapshot testing
Jest permet de tester la structure des objets avec les snapshots :
typescript
it('should match user object snapshot', () => {
const user = {
id: 1,
name: 'John Doe',
email: '[email protected]'
};
expect(user).toMatchSnapshot();
});
Tests avec mockReturnValue et mockImplementation
Jest offre des méthodes de mock plus flexibles :
typescript
// Mock avec valeur de retour
const mockService = {
getData: jest.fn().mockReturnValue('mocked data')
};
// Mock avec implémentation personnalisée
const mockService = {
getData: jest.fn().mockImplementation((id: number) => {
return id > 0 ? 'valid data' : 'invalid data';
})
};
Mock des timers
Jest permet de contrôler les timers pour tester les opérations asynchrones :
typescript
it('should handle timeout', () => {
jest.useFakeTimers();
let callback = jest.fn();
setTimeout(callback, 1000);
// Avancer le temps
jest.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalled();
jest.useRealTimers();
});
Bonnes pratiques Jest spécifiques
Utilisation des mocks avec Jest
Jest offre un système de mocking très puissant et plus simple que Jasmine :
typescript
// Mock d'un service HTTP avec Jest
const mockHttpService = {
get: jest.fn().mockReturnValue(of(mockData)),
post: jest.fn().mockResolvedValue(mockResponse),
put: jest.fn().mockRejectedValue(new Error('Network error')),
delete: jest.fn().mockImplementation((url) => {
return url.includes('admin') ? of(successResponse) : throwError('Unauthorized');
})
};
// Dans le test
beforeEach(() => {
// Jest permet de réinitialiser tous les mocks facilement
jest.clearAllMocks();
});
Tests avec fakeAsync et Jest timers
Jest améliore aussi la gestion des timers :
typescript
import { fakeAsync, tick } from '@angular/core/testing';
it('should handle async operations with Jest timers', fakeAsync(() => {
// Arrange
jest.useFakeTimers();
let result: any;
// Act
service.asyncOperation().subscribe(data => {
result = data;
});
// Jest permet un contrôle plus fin des timers
jest.advanceTimersByTime(1000);
tick();
// Assert
expect(result).toBeDefined();
// Nettoyage
jest.useRealTimers();
}));
Matchers Jest supplémentaires
Jest offre des matchers plus expressifs :
typescript
it('should use Jest-specific matchers', () => {
const mockFunction = jest.fn();
mockFunction('test');
// Matchers Jest plus expressifs
expect(mockFunction).toHaveBeenCalledWith('test');
expect(mockFunction).toHaveBeenCalledTimes(1);
expect(mockFunction).toHaveBeenLastCalledWith('test');
expect(mockFunction).toHaveReturnedWith(undefined);
// Matchers pour les tableaux et objets
expect(['a', 'b', 'c']).toContain('b');
expect({ name: 'John', age: 30 }).toHaveProperty('name', 'John');
expect(mockFunction.mock.calls[0]).toEqual(['test']);
});
Avantages Jest vs Jasmine
- Performance : Jest est 3-5x plus rapide
- Mocking : API plus simple et puissante
- Snapshots : Tests de régression automatiques
- Configuration : Moins de configuration nécessaire
- Intégration : Meilleure intégration avec les outils modernes