Tester un service

  • Générer un nouveau projet Angular.
ng new angular-tests-par-la-pratique

Tester une méthode

  • Générer un service
ng g service compteur

Les fichiers suivants sont créés :

/src/app
    compteur.service.ts
    compteur.service.spec.ts

Un service est créé :

import { Injectable } from '@angular/core';

@Injectable()
export class CompteurService {

  constructor() { }

}

Le test associé aussi :

// TestBed est une classe utilitaire fournie par Angular.
// Elle permet de créer un module Angular spécifiquement pour les tests
// inject est une fonction permettant de bénéficier de 
// l'injection de dépendance dans le cadre de nos tests.
import { TestBed, inject } from '@angular/core/testing';

// La classe compteur
import { CompteurService } from './compteur.service';


// describe est une fonction du framework Jasmine
// Il définit un ensemble de cas de tests
describe('CompteurService', () => {

  // beforeEach est une fonction Jasmine exécutée avant chaque cas de test
  beforeEach(() => {

    // création d'un module Angular pour le test
    // ce module est composé d'un service CompteurService
    TestBed.configureTestingModule({
      providers: [CompteurService]
    });
  });

  // it est une fonction Jasmine
  // il représente un cas de test
  // inject() permet ici de récupérer une instance du service via l'injection de dépendance.
  it('should be created', inject([CompteurService], (service: CompteurService) => {

    // A ce stade, nous avons une instance de CompteurService via la variable service

    // expect et toBeTruthy() sont des assertions Jasmine
    // ici le test vérifie que le service est instancié
    expect(service).toBeTruthy();
  }));
});
  • Lancer l'exécution des tests
ng test
  • Compléter le service comme suit :
import { Injectable } from "@angular/core";

@Injectable()
export class CompteurService {
  private _nombre = 0;

  constructor() {}

  incrementer(): number {
    return 0;
  }
}
  • Créer des cas de test pour la méthode incrementer.
it("le premier appel à incrementer() retourne 1", inject([CompteurService], (service: CompteurService) => {
    const resultat = service.incrementer();

      expect(resultat).toBe(1);

    })
);

it("deux appels à incrementer() retourne 2", inject([CompteurService], (service: CompteurService) => {
    service.incrementer();
    const resultat = service.incrementer();

      expect(resultat).toBe(2);

    })
);
  • Vérifier que le test est KO. Compléter le service CompteurService pour rendre ces tests passant.

Tester une méthode utilisant le client HTTP

  • Générer un service
ng g service posts

Les fichiers suivants sont créés :

/src/app
    posts.service.ts
    posts.service.spec.ts
  • Ajouter le module HTTP Client
import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { HttpClientModule } from "@angular/common/http";

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

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, HttpClientModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}
  • Compléter le service PostsService comme suit :
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { Observable } from "rxjs";

@Injectable()
export class PostsService {
  constructor(private _http: HttpClient) {}

  recupererTousLesPosts(): Observable<any> {
    return this._http.get("https://jsonplaceholder.typicode.com/posts");
  }
}
  • Compléter le test associé :
import { TestBed, inject } from "@angular/core/testing";

// Angular fournit un support pour les tests du client HTTP 
// via le module : HttpClientTestingModule
// Toutes les requêtes sont mockées
// HttpTestingController permet de contrôler le mock généré par Angular 
import {
  HttpClientTestingModule,
  HttpTestingController
} from "@angular/common/http/testing";

import { PostsService } from "./posts.service";

describe("PostsService", () => {

  // variable locale du contrôleur du mock HTTP Angular
  let httpTestingController: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      // import du module HTTP Client Test
      imports: [HttpClientTestingModule],
      providers: [PostsService]
    });

    // récupération de l'instance du contrôleur du mock HTTP Angular
    httpTestingController = TestBed.get(HttpTestingController);
  });

  // ...

  it("recupererTousLesPosts() envoie une requête HTTP vers https://jsonplaceholder.typicode.com/posts",
    inject([PostsService], (service: PostsService) => {

      // invocation de la méthode recupererTousLesPosts()
      // vérification du corps de la réponse HTTP
      service.recupererTousLesPosts().subscribe(posts => {
        // le résultat contient exactement 2 posts
        expect(posts.length).toBe(2);

        // vérification des résultats des titres
        expect(posts[0]["title"]).toBe("Titre 1");
        expect(posts[1]["title"]).toBe("Titre 2");
      });

      // vérifie qu'un appel HTTP vers https://jsonplaceholder.typicode.com/posts
      // a été émis une seule fois
      const requete = httpTestingController.expectOne(
        "https://jsonplaceholder.typicode.com/posts"
      );

      // vérifie que la requête émise à la méthode GET
      expect(requete.request.method).toEqual("GET");

      // déclenchement de la réponse HTTP
      // les observateurs sont alors notifiés
      requete.flush([{ id: 1, title: "Titre 1" }, { id: 2, title: "Titre 2" }]);
    })
  );

  afterEach(() => {
    // vérifie qu'il n'y aucune requête HTTP non prévue déclenchée
    httpTestingController.verify();
  });
});

La documentation officielle : https://angular.io/guide/http#testing-http-requests.

results matching ""

    No results matching ""