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.

HttpTestingController : Tester les requêtes HTTP

L'HttpTestingController est un utilitaire Angular qui permet d'intercepter et de simuler les requêtes HTTP dans vos tests unitaires. C'est comme avoir un contrôleur de trafic pour vos appels API !

Pourquoi utiliser HttpTestingController ?

Imaginez que vous testez une application de météo. Sans HttpTestingController, votre test ferait un vrai appel à l'API météo, ce qui serait lent, coûteux et imprévisible. Avec HttpTestingController, vous contrôlez exactement ce que "l'API" renvoie, comme si vous étiez le serveur vous-même.

Les concepts clés

1. HttpTestingController

C'est l'outil principal qui intercepte toutes les requêtes HTTP de votre application pendant les tests. Il vous permet de :

  • Vérifier quelles requêtes ont été faites
  • Contrôler les réponses retournées
  • Simuler des erreurs réseau

2. httpMock.expectOne()

Cette méthode attrape une requête HTTP spécifique et vous donne le contrôle total sur sa réponse :

typescript
// Intercepte la requête vers /users
const req = httpMock.expectOne('/users');

// Vérifie que c'est bien une requête GET
expect(req.request.method).toBe('GET');

// Vérifie le corps de la requête (pour POST/PUT)
expect(req.request.body).toEqual({ name: 'John' });

3. req.flush() - Simuler une réponse réussie

typescript
// Simule une réponse du serveur
req.flush([
  { id: 1, name: 'John Doe' },
  { id: 2, name: 'Jane Smith' }
]);

4. req.error() - Simuler une erreur réseau

typescript
// Simule une erreur réseau (pas d'internet, serveur inaccessible)
req.error(new ProgressEvent('error'));

5. httpMock.verify() - Vérifier que tout est testé

typescript
afterEach(() => {
  httpMock.verify();
});

Cette méthode garantit qu'aucune requête HTTP n'est restée en attente. Si votre code fait 2 requêtes mais que vous n'avez testé qu'une seule, le test échoue.

Exemple complet

Créons un composant qui affiche une liste d'utilisateurs :

typescript
import { Component, OnInit, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-user-list',
  standalone: true,
  template: `
    <h1>Liste des utilisateurs</h1>
    <ul>
      @for (user of users; track user.id) {
        <li>{{ user.name }}</li>
      }
    </ul>
  `
})
export class UserListComponent implements OnInit {
  private http = inject(HttpClient);
  users: User[] = [];

  ngOnInit() {
    // Récupère la liste des utilisateurs depuis l'API
    this.http.get<User[]>('/users')
      .subscribe(users => {
        this.users = users;
      });
  }
}

Maintenant, testons ce composant avec HttpTestingController :

typescript
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { provideHttpClient } from '@angular/common/http';
import { UserListComponent } from './user-list.component';

describe('UserListComponent', () => {
  let component: UserListComponent;
  let fixture: ComponentFixture<UserListComponent>;
  let httpMock: HttpTestingController;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [UserListComponent],
      providers: [
        provideHttpClient(),
        provideHttpClientTesting()
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(UserListComponent);
    component = fixture.componentInstance;
    httpMock = TestBed.inject(HttpTestingController);
  });

  afterEach(() => {
    // Vérifie qu'aucune requête HTTP n'est restée en attente
    httpMock.verify();
  });

  it('affiche la liste des utilisateurs à l\'init', () => {
    // 1. Données factices pour simuler la réponse de l'API
    const usersMock = Array.from({ length: 10 }, (_, i) => ({
      id: i + 1,
      name: `User ${i + 1}`
    }));

    // 2. Lance ngOnInit (et donc l'appel HTTP du composant)
    fixture.detectChanges();

    // 3. Intercepte la requête vers /users
    const req = httpMock.expectOne('/users');
    expect(req.request.method).toBe('GET');

    // 4. Renvoie la réponse factice
    req.flush(usersMock);

    // 5. Met à jour le template après la réponse
    fixture.detectChanges();

    // 6. Vérifie que les utilisateurs s'affichent dans le DOM
    const li = fixture.nativeElement.querySelectorAll('li');
    expect(li.length).toBe(10);
    expect(li[0].textContent).toBe('User 1');
  });
});

Tester les erreurs

Vous pouvez aussi tester comment votre composant gère les erreurs :

typescript
it('gère les erreurs de réseau', () => {
  fixture.detectChanges();

  const req = httpMock.expectOne('/users');
  
  // Simule une erreur réseau
  req.error(new ProgressEvent('error'));

  fixture.detectChanges();

  // Vérifie que le composant gère l'erreur correctement
  expect(component.users).toEqual([]);
});

Tester les requêtes POST

Pour tester l'envoi de données :

typescript
it('envoie un nouvel utilisateur', () => {
  const newUser = { name: 'John Doe' };
  
  // Simule l'ajout d'un utilisateur
  component.addUser(newUser);
  
  const req = httpMock.expectOne('/users');
  expect(req.request.method).toBe('POST');
  expect(req.request.body).toEqual(newUser);
  
  // Simule la réponse du serveur
  req.flush({ id: 1, ...newUser });
});

Bonne pratique

Toujours appeler httpMock.verify() dans afterEach() pour s'assurer que toutes les requêtes HTTP ont été testées. Cela évite les tests qui passent par hasard !

Attention

N'oubliez pas d'importer provideHttpClientTesting() dans vos providers. Sans cela, HttpTestingController ne fonctionnera pas !

Résumé

L'HttpTestingController vous donne un contrôle total sur vos requêtes HTTP dans les tests :

  • expectOne() → Attrape une requête spécifique
  • flush() → Simule une réponse réussie
  • error() → Simule une erreur réseau
  • verify() → Garantit que tout a été testé

C'est l'outil parfait pour tester vos composants qui communiquent avec des APIs, sans dépendre de vrais serveurs externes !