Écrire des tests unitaires isolés pour vos pipes Angular
Les pipes Angular nous permettent de transformer des données avant de les afficher. Angular nous fournit une large gamme de pipes de base, mais nous devons parfois implémenter nos propres pipes. Dans ce cas, il faut aussi écrire des tests unitaires pour nos pipes.
Le pipe fait partie des concepts Angular les plus simples. Il s’agit d’une classe TypeScript munie du décorateur
@Pipe
et qui implémente l’interface PipeTransform
. Cette interface comporte uniquement une méthode, la méthode
transform
comme le montre le bout de code suivant :
interface PipeTransform { transform(value: any, ...args: any[]): any;}
La méthode transform
prend une donnée en entrée, la transforme, et la retourne pour qu’on puisse l’afficher dans nos
templates avec un bon formatage.
Les pipes Angular sont faciles à tester, car ils n’interagissent que très rarement avec le DOM.
Techniquement, nous pouvons donc les tester sans nous servir des utilitaires de test fournis par Angular ou TestBed
.
On peut écrire deux types de tests unitaires pour nos pipes Angular :
- des tests unitaires en isolation (sans
TestBed
), - des tests unitaires en intégration (avec
TestBed
).
Dans cet article, nous allons apprendre à écrire des tests unitaires isolés pour nos pipes Angular.
Dans un prochain article, nous verrons comment écrire des
tests unitaires en intégration avec TestBed
.
On parle de test unitaire isolé lorsqu’on teste le pipe comme si c’était une banale classe TypeScript.
On fait fi du fait qu’un pipe est utilisé dans des templates Angular. En un mot, on ne teste que la méthode transform
du pipe.
Le code utilisé pour l’exemple (mean.pipe.ts
)
Pour le reste de l’article, on va utiliser un pipe dont le but est de prendre en entrée un tableau d’entier et de retourner en sortie la moyenne des éléments qui le constituent. En voici le code :
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({ name: 'mean',})export class MeanPipe implements PipeTransform { transform(value: number[]): number { if (!Array.isArray(value)) { return value; } if (value.length === 0) { return undefined; } const sum = value.reduce((n: number, m: number) => n + m, 0); return sum / value.length; }}
On voit dans ce bout de code que:
- La classe
MeanPipe
implémente l’interfacePipeTransform
. - La méthode
transform
retourne la moyenne des éléments du tableauvalue
qui lui est passé en entrée.
Testons cet pipe en isolation (mean.pipe.spec.ts
)
Lorsque nous utilisons le Angular CLI pour générer un notre pipe, le CLI génère aussi un squelette de test se présentant comme suit :
describe('MeanPipe', () => { it('create an instance', () => { const pipe = new MeanPipe(); expect(pipe).toBeTruthy(); });});
Cette exemple de code :
- crée une nouvelle instance de
MeanPipe
, - vérifie que le pipe est correctement instancié.
Ce test unitaire ne sert pas vraiment à grand-chose, mais c’est un bon point de départ. À partir de là, nous pouvons écrire des tests unitaires qui font plus sens.
Testons le comportement de notre pipe avec de mauvais inputs
La suite de tests Bad inputs
teste le pipe lorsque nous lui passons des valeurs incorrectes comme un object {a: 'a'}
, null
ou un tableau vide.
describe('MeanPipe', () => { const pipe = new MeanPipe(); // ...
describe('Bad inputs', () => { it('should return the object without modification', () => { expect(pipe.transform({ a: 'a' } as any)).toEqual({ a: 'a' } as any); });
it('should return null ', () => { expect(pipe.transform(null)).toEqual(null); });
it('should return undefined', () => { expect(pipe.transform([])).toEqual(undefined); }); });});
Testons le comportement de notre pipe avec de bons inputs
La suite de tests Good inputs
teste le pipe lorsque nous lui passons des valeurs correctes.
describe('MeanPipe', () => { const pipe = new MeanPipe(); // ...
describe('Good inputs', () => { it('should return 1', () => { expect(pipe.transform([1])).toEqual(1); });
it('should return 0', () => { expect(pipe.transform([1, -1])).toEqual(0); });
it('should return 1', () => { expect(pipe.transform([1, 1])).toEqual(1); });
it('should return -1', () => { expect(pipe.transform([-1, -1])).toEqual(-1); }); });});
Nous n’avons pas eu besoin d’utiliser un bloc BeforeEach parce que cet pipe est pure; sa méthode transform
est sans état.
Conclusion
Dans cet article, nous avons appris qu’il y avait deux types de tests unitaires pour les pipes Angular : les tests unitaires isolés et les tests unitaires intégrés. Nous avons mis l’accent sur les tests unitaires isolés et vu à quel point c’était facile d’en écrire. Dans un prochain article, nous allons apprendre à écrire des tests unitaires intégrés pour nos pipes Angular.
Vous aimez ce blog ?
Suivez-moi sur Twitter pour plus de contenu !
Rejoignez la newsletter pour du contenu de grande qualité dans votre boite mail