Les proves de components són una part essencial del desenvolupament d'aplicacions Angular. Aquest tipus de proves asseguren que els components funcionin correctament de manera aïllada, sense dependre d'altres parts de l'aplicació. En aquesta secció, aprendrem com configurar i escriure proves per als components Angular utilitzant el framework de proves Jasmine i l'entorn de proves Karma.
Objectius
- Entendre la importància de les proves de components.
- Configurar l'entorn de proves per a components Angular.
- Escriure proves unitàries per a components.
- Utilitzar mocks i espies per a proves més efectives.
Configuració de l'entorn de proves
Angular CLI ve amb Jasmine i Karma preconfigurats per a proves. Quan crees un nou projecte Angular, l'entorn de proves ja està configurat. Per executar les proves, simplement utilitza el següent comandament:
Aquest comandament executarà Karma, que a la vegada executarà les proves definides amb Jasmine.
Estructura bàsica d'una prova de component
A continuació, es mostra un exemple bàsic d'una prova de component. Suposem que tenim un component HelloComponent
que mostra un missatge de benvinguda.
Component: hello.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-hello', template: '<h1>{{message}}</h1>' }) export class HelloComponent { message: string = 'Hola, món!'; }
Prova: hello.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HelloComponent } from './hello.component'; describe('HelloComponent', () => { let component: HelloComponent; let fixture: ComponentFixture<HelloComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ HelloComponent ] }) .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(HelloComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('hauria de crear el component', () => { expect(component).toBeTruthy(); }); it('hauria de mostrar el missatge de benvinguda', () => { const compiled = fixture.nativeElement; expect(compiled.querySelector('h1').textContent).toContain('Hola, món!'); }); });
Explicació del codi
- Importacions: Importem les funcions necessàries de
@angular/core/testing
i el component que volem provar. - Descripció de la prova: Utilitzem
describe
per agrupar les proves relacionades ambHelloComponent
. - Configuració del TestBed:
TestBed
és una utilitat d'Angular per configurar i inicialitzar l'entorn de proves. Aquí, declarem el component que volem provar. - Creació del component: Utilitzem
TestBed.createComponent
per crear una instància del component i assignar-la afixture
icomponent
. - Proves: Utilitzem
it
per definir les proves. En aquest cas, comprovem que el component es crea correctament i que el missatge de benvinguda es mostra correctament.
Mocks i espies
En proves de components, sovint necessitem simular serveis o altres dependències. Això es pot fer utilitzant mocks i espies.
Exemple amb un servei
Suposem que HelloComponent
depèn d'un servei GreetingService
per obtenir el missatge de benvinguda.
Servei: greeting.service.ts
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class GreetingService { getMessage(): string { return 'Hola, món!'; } }
Component: hello.component.ts
import { Component, OnInit } from '@angular/core'; import { GreetingService } from './greeting.service'; @Component({ selector: 'app-hello', template: '<h1>{{message}}</h1>' }) export class HelloComponent implements OnInit { message: string; constructor(private greetingService: GreetingService) {} ngOnInit(): void { this.message = this.greetingService.getMessage(); } }
Prova: hello.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { HelloComponent } from './hello.component'; import { GreetingService } from './greeting.service'; class MockGreetingService { getMessage(): string { return 'Hola, món!'; } } describe('HelloComponent', () => { let component: HelloComponent; let fixture: ComponentFixture<HelloComponent>; let greetingService: GreetingService; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ HelloComponent ], providers: [ { provide: GreetingService, useClass: MockGreetingService } ] }) .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(HelloComponent); component = fixture.componentInstance; greetingService = TestBed.inject(GreetingService); fixture.detectChanges(); }); it('hauria de crear el component', () => { expect(component).toBeTruthy(); }); it('hauria de mostrar el missatge de benvinguda', () => { const compiled = fixture.nativeElement; expect(compiled.querySelector('h1').textContent).toContain('Hola, món!'); }); });
Explicació del codi
- Mock del servei: Creem una classe
MockGreetingService
que simula el comportament del servei real. - Proveïdors: En la configuració del
TestBed
, utilitzemproviders
per substituir el servei real pel mock. - Injecció del servei: Utilitzem
TestBed.inject
per obtenir una instància del servei (en aquest cas, el mock).
Exercicis pràctics
Exercici 1
Crea un component CounterComponent
que tingui un botó per incrementar un comptador. Escriu proves per assegurar-te que el comptador s'incrementa correctament.
Component: counter.component.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-counter', template: ` <p>Comptador: {{count}}</p> <button (click)="increment()">Incrementar</button> ` }) export class CounterComponent { count: number = 0; increment(): void { this.count++; } }
Prova: counter.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing'; import { CounterComponent } from './counter.component'; describe('CounterComponent', () => { let component: CounterComponent; let fixture: ComponentFixture<CounterComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [ CounterComponent ] }) .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(CounterComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('hauria de crear el component', () => { expect(component).toBeTruthy(); }); it('hauria d\'incrementar el comptador quan es fa clic al botó', () => { const compiled = fixture.nativeElement; const button = compiled.querySelector('button'); button.click(); fixture.detectChanges(); expect(compiled.querySelector('p').textContent).toContain('Comptador: 1'); }); });
Solució
- Creació del component: El component
CounterComponent
té una propietatcount
i un mètodeincrement
que incrementa el comptador. - Prova del component: La prova comprova que el component es crea correctament i que el comptador s'incrementa quan es fa clic al botó.
Resum
En aquesta secció, hem après com configurar i escriure proves per a components Angular. Hem vist com utilitzar mocks i espies per simular dependències i com escriure proves unitàries efectives. Les proves de components són una eina poderosa per assegurar la qualitat i la fiabilitat de les nostres aplicacions Angular.
Curs d'Angular 2+
Mòdul 1: Introducció a Angular
- Què és Angular?
- Configuració de l'entorn de desenvolupament
- La teva primera aplicació Angular
- Arquitectura d'Angular
Mòdul 2: Conceptes bàsics de TypeScript
- Introducció a TypeScript
- Variables i tipus de dades en TypeScript
- Funcions i funcions fletxa
- Classes i interfícies
Mòdul 3: Components i plantilles
Mòdul 4: Directives i pipes
Mòdul 5: Serveis i injecció de dependències
Mòdul 6: Enrutament i navegació
Mòdul 7: Formularis en Angular
Mòdul 8: Client HTTP i observables
- Introducció al client HTTP
- Realització de sol·licituds HTTP
- Gestió de respostes HTTP
- Ús d'observables