Skip to content

Tester un composant avec des notions asynchrones

Pour tester si une liste d'utilisateurs récupérée avec une requête HTTP s'affiche correctement dans le template d'un composant Angular, vous pouvez suivre les étapes ci-dessous :

  1. Dans votre composant, créez une propriété users pour stocker la liste d'utilisateurs et une méthode getUsers() pour récupérer la liste d'utilisateurs en utilisant une requête HTTP. Par exemple :
ts
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  users: any[];

  constructor(private http: HttpClient) { }

  ngOnInit() {
    this.getUsers();
  }

  getUsers() {
    this.http.get('https://jsonplaceholder.typicode.com/users')
      .subscribe(users => {
        this.users = users;
      });
  }
}
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  users: any[];

  constructor(private http: HttpClient) { }

  ngOnInit() {
    this.getUsers();
  }

  getUsers() {
    this.http.get('https://jsonplaceholder.typicode.com/users')
      .subscribe(users => {
        this.users = users;
      });
  }
}
  1. Dans le template du composant, affichez la liste d'utilisateurs en utilisant la directive ngFor. Par exemple :
html
<ul>
  <li *ngFor="let user of users">
    {{ user.name }}
  </li>
</ul>
<ul>
  <li *ngFor="let user of users">
    {{ user.name }}
  </li>
</ul>
  1. Dans le fichier de test unitaire du composant, importez les modules HttpClientTestingModule et HttpTestingController depuis @angular/common/http/testing.

  2. Dans la méthode beforeEach() de votre test unitaire, configurez le module de test en utilisant le HttpClientTestingModule. Par exemple :

ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

import { AppComponent } from './app.component';

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

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ AppComponent ],
      imports: [ HttpClientTestingModule ]
    })
    .compileComponents();

    httpMock = TestBed.inject(HttpTestingController);
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

  // tests go here
});
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

import { AppComponent } from './app.component';

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

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ AppComponent ],
      imports: [ HttpClientTestingModule ]
    })
    .compileComponents();

    httpMock = TestBed.inject(HttpTestingController);
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

  // tests go here
});

httpMock.verify() ?

httpMock.verify() est une méthode utilisée dans les tests unitaires pour vérifier si toutes les requêtes HTTP programmées avec httpMock ont été effectuées correctement.

  1. Dans la méthode beforeEach(), après avoir configuré le module de test et simulé la réponse HTTP, appelez la méthode fixture.detectChanges() pour mettre à jour le template avec les nouvelles valeurs des variables du composant.

  2. Dans la méthode it() du test, utilisez la méthode whenStable() pour attendre la résolution de toutes les opérations asynchrones avant de vérifier le template. Par exemple :

ts
it('should display a list of users', async () => {
    httpMock.expectOne('https://jsonplaceholder.typicode.com/users')
        .flush([
          { name: 'Leanne Graham' },
          { name: 'Ervin Howell' },
        // etc.
    ]);

    fixture.detectChanges(); // déclenche ngOnInit
    await fixture.whenStable(); // Garantit que toutes les opérations asynchrones se sont terminées 
    fixture.detectChanges(); // Affiche le résultat dans le template
    const userElements = fixture.nativeElement.querySelectorAll('li');
    expect(userElements.length).toBe(10);
    expect(userElements[0].textContent).toBe('Leanne Graham');
    expect(userElements[1].textContent).toBe('Ervin Howell');
});
it('should display a list of users', async () => {
    httpMock.expectOne('https://jsonplaceholder.typicode.com/users')
        .flush([
          { name: 'Leanne Graham' },
          { name: 'Ervin Howell' },
        // etc.
    ]);

    fixture.detectChanges(); // déclenche ngOnInit
    await fixture.whenStable(); // Garantit que toutes les opérations asynchrones se sont terminées 
    fixture.detectChanges(); // Affiche le résultat dans le template
    const userElements = fixture.nativeElement.querySelectorAll('li');
    expect(userElements.length).toBe(10);
    expect(userElements[0].textContent).toBe('Leanne Graham');
    expect(userElements[1].textContent).toBe('Ervin Howell');
});

Dans ce code, le test attend la résolution de toutes les opérations asynchrones en appelant la méthode whenStable() avant de vérifier les éléments du template. Cela garantit que les données récupérées par la requête HTTP sont à jour lorsque le test vérifie les éléments du template.

En utilisant la méthode whenStable() dans ce test unitaire, vous pouvez être sûr que les données dans le template sont à jour et que le test vérifie la bonne liste d'utilisateurs.

C'est quoi un mock et httpMock ?

Un mock est un objet de substitution utilisé dans les tests unitaires pour simuler le comportement d'un objet réel. Les mocks peuvent être utilisés pour simuler des réponses à des appels de fonction, des retours de valeur ou des événements d'un objet réel, afin de tester le comportement d'une partie de votre code sans avoir à utiliser l'objet réel.

Dans l'exemple de test unitaire, l'objet httpMock est un mock de l'objet HttpTestingController qui est utilisé pour simuler une réponse HTTP à une requête faite par le composant. Le mock est utilisé pour vérifier si la requête a été faite et pour simuler une réponse HTTP pour tester le comportement du composant en réponse à cette requête.

Utiliser des mocks dans les tests unitaires est utile pour isoler le code que vous testez et pour éviter les dépendances externes qui pourraient affecter les résultats des tests. Cela permet également de tester des parties spécifiques de votre code de manière plus précise et de détecter les erreurs plus facilement.

Pourquoi utiliser HttpClientTestingModule au lieu de HttpClientModule ?

Dans les tests unitaires, il est recommandé d'utiliser le module HttpClientTestingModule au lieu du module HttpClientModule pour les opérations HTTP. Le module HttpClientTestingModule est conçu pour les tests unitaires et permet de simuler des réponses HTTP dans les tests, ce qui n'est pas possible avec le module HttpClientModule.

En utilisant le module HttpClientTestingModule, vous pouvez facilement contrôler les réponses HTTP dans vos tests unitaires et vérifier si votre code gère correctement ces réponses. Cela permet de tester les parties de votre code qui utilisent des requêtes HTTP de manière plus précise et sans avoir à se connecter à un serveur réel.