Découvrez les nouveautés d'Angular 20 en quelques minutes

Angular 20 arrive avec plusieurs nouveautés et stabilisation des API: Zoneless, les APIs resource() et httpResource(), un nouveau runner de tests, etc. La vidéo vous donne un aperçu de ces nouveautés.

Abonnez-vous à notre chaîne

Pour profiter des prochaines vidéos sur Angular, abonnez-vous à la nouvelle chaîne YouTube !

Skip to content

Vous souhaitez recevoir de l'aide sur ce sujet ? rejoignez la communauté Angular.fr sur Discord.

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