Skip to content

Tester le composant

Le composant pourrait être le suivant:

ts
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-mon-composant',
  template: `
    <h1>{{ title }}</h1>
    <button (click)="addUser()">Ajouter un utilisateur</button>
    <ul>
      <li *ngFor="let user of users">{{ user }}</li>
    </ul>
  `,
  styles: []
})
export class MonComposantComponent implements OnInit {
  title = 'Liste des utilisateurs';
  users = ['Utilisateur 1', 'Utilisateur 2'];

  constructor() { }

  ngOnInit() {
  }

  addUser() {
    this.users.push('Nouvel utilisateur');
  }
}
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-mon-composant',
  template: `
    <h1>{{ title }}</h1>
    <button (click)="addUser()">Ajouter un utilisateur</button>
    <ul>
      <li *ngFor="let user of users">{{ user }}</li>
    </ul>
  `,
  styles: []
})
export class MonComposantComponent implements OnInit {
  title = 'Liste des utilisateurs';
  users = ['Utilisateur 1', 'Utilisateur 2'];

  constructor() { }

  ngOnInit() {
  }

  addUser() {
    this.users.push('Nouvel utilisateur');
  }
}

Ce composant affiche une liste d'utilisateurs avec un titre et un bouton pour ajouter un utilisateur à la liste. Lorsque le bouton est cliqué, la méthode addUser est appelée pour ajouter un nouvel utilisateur à la liste. Voici un exemple de test unitaire qui vérifie si un élément du template a la bonne valeur :

ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MonComposantComponent } from './mon-composant.component';

describe('MonComposantComponent', () => {
  let component: MonComposantComponent;
  let fixture: ComponentFixture<MonComposantComponent>;

  beforeEach(async() => {
    await TestBed.configureTestingModule({
      declarations: [ MonComposantComponent ]
    })
    .compileComponents();
  });

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

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should have the correct title', () => {
    const titleElement = fixture.nativeElement.querySelector('h1');
    expect(titleElement.textContent).toBe('Mon titre');
  });
});
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MonComposantComponent } from './mon-composant.component';

describe('MonComposantComponent', () => {
  let component: MonComposantComponent;
  let fixture: ComponentFixture<MonComposantComponent>;

  beforeEach(async() => {
    await TestBed.configureTestingModule({
      declarations: [ MonComposantComponent ]
    })
    .compileComponents();
  });

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

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should have the correct title', () => {
    const titleElement = fixture.nativeElement.querySelector('h1');
    expect(titleElement.textContent).toBe('Mon titre');
  });
});

Dans cet exemple, le test vérifie si l'élément <h1> avec le texte Mon titre est présent dans le template du composant. Si l'élément est présent et a la bonne valeur, le test passera avec succès. Si l'élément n'est pas présent ou n'a pas la bonne valeur, le test échouera.

Qu'est ce que configureTestingModule() ?

configureTestingModule est une méthode de la classe TestBed dans Angular, qui permet de configurer un module de test pour le composant à tester. Elle prend en entrée un objet qui décrit les dépendances du composant, notamment les déclarations de composants, les fournisseurs de services, les imports de modules, etc.

L'objet passé à configureTestingModule définit le contexte dans lequel le composant sera testé, en incluant les dépendances nécessaires pour que le composant fonctionne correctement. C'est donc un élément clé pour s'assurer que les tests unitaires sont fiables et reflètent le comportement réel du composant.

Dans ce cas précis, le code declarations: [ MonComposantComponent ] indique que le composant MonComposantComponent est déclaré dans le module de test. Cela signifie que le composant sera disponible pour être utilisé dans le test unitaire.

Qu'est ce que compileComponents() ?

compileComponents() est une méthode de la classe TestBed qui compile les composants déclarés dans le module de test. Elle est utilisée pour garantir que les composants soient compilés avant le début des tests. Si compileComponents() n'est pas appelé, les tests pourraient échouer en raison de la non-compilation des composants.

L'utilisation de await avec compileComponents() est nécessaire car cette méthode retourne une promesse qui doit être résolue avant de continuer avec les tests. En utilisant await, nous pouvons garantir que les composants seront compilés avant de commencer à tester le composant MonComposantComponent.

Pourquoi utiliser fixture.detectChanges() ?

fixture.detectChanges() est utilisé pour déclencher la détection des changements dans le composant, ce qui permet de mettre à jour les propriétés et les vues associées au composant. Cela est appelé avant chaque test pour garantir que le composant soit en état cohérent pour le test.

Si fixture.detectChanges() n'est pas appelé, les propriétés et les vues associées au composant ne seront pas mises à jour, ce qui peut entraîner des résultats incorrects pour les tests. Les tests peuvent échouer ou donner des résultats inattendus en raison de la non-mise à jour du composant.

Tester après le clic

Voici un exemple de test unitaire qui vérifie que l'utilisateur a bien été ajouté lorsque le bouton est cliqué :

ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MonComposantComponent } from './mon-composant.component';

describe('MonComposantComponent', () => {
  let component: MonComposantComponent;
  let fixture: ComponentFixture<MonComposantComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ MonComposantComponent ]
    })
    .compileComponents();
  });

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

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should add a user to the list when the button is clicked', () => {
    const button = fixture.nativeElement.querySelector('button');
    button.click();
    fixture.detectChanges();

    const users = fixture.nativeElement.querySelectorAll('li');
    expect(users.length).toBe(3);
    expect(users[2].textContent).toBe('Nouvel utilisateur');
  });
});
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MonComposantComponent } from './mon-composant.component';

describe('MonComposantComponent', () => {
  let component: MonComposantComponent;
  let fixture: ComponentFixture<MonComposantComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ MonComposantComponent ]
    })
    .compileComponents();
  });

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

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should add a user to the list when the button is clicked', () => {
    const button = fixture.nativeElement.querySelector('button');
    button.click();
    fixture.detectChanges();

    const users = fixture.nativeElement.querySelectorAll('li');
    expect(users.length).toBe(3);
    expect(users[2].textContent).toBe('Nouvel utilisateur');
  });
});

L'appel à fixture.detectChanges() après le clic sur le bouton est nécessaire pour que les modifications apportées au composant soient reflétées dans la vue. En effet, lorsque le bouton est cliqué, cela peut déclencher des mises à jour du modèle de données du composant, mais ces mises à jour ne seront pas reflétées dans la vue tant que fixture.detectChanges() n'a pas été appelé.

Il permet à Angular de détecter les modifications apportées au modèle de données et de mettre à jour la vue en conséquence. C'est donc un élément clé pour s'assurer que les tests unitaires sont fiables et reflètent le comportement réel du composant.