En aquest tema, aprendrem com realitzar proves unitàries per als serveis d'Angular. Els serveis són una part fonamental de qualsevol aplicació Angular, ja que encapsulen la lògica de negoci i proporcionen funcionalitats reutilitzables. Les proves de serveis asseguren que aquesta lògica funcioni correctament i que els serveis es comportin com s'espera.
Objectius
- Comprendre la importància de les proves de serveis.
- Configurar l'entorn de proves per als serveis.
- Escriure proves unitàries per als serveis d'Angular.
- Utilitzar simulacions (mocks) per a les dependències dels serveis.
- Importància de les proves de serveis
Les proves de serveis són crucials per diverses raons:
- Fiabilitat: Asseguren que la lògica de negoci funcioni correctament.
- Mantenibilitat: Faciliten la detecció de regressions quan es fan canvis en el codi.
- Documentació: Les proves actuen com a documentació viva del comportament esperat dels serveis.
- Configuració de l'entorn de proves
Angular utilitza Jasmine i Karma per a les proves unitàries. A continuació, es mostra com configurar l'entorn de proves per als serveis.
Instal·lació de dependències
Assegura't que les dependències de Jasmine i Karma estiguin instal·lades. Si has creat el projecte amb Angular CLI, aquestes dependències ja haurien d'estar presents.
Configuració del fitxer de proves
El fitxer de proves per a un servei es troba normalment a la mateixa carpeta que el servei, amb el sufix .spec.ts
. Per exemple, si tens un servei data.service.ts
, el fitxer de proves seria data.service.spec.ts
.
- Escriure proves unitàries per als serveis
Exemple de servei
Suposem que tenim el següent servei data.service.ts
:
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class DataService { constructor() { } getData(): string { return 'Hello, Angular!'; } }
Exemple de fitxer de proves
A continuació, es mostra com escriure proves unitàries per al servei DataService
.
import { TestBed } from '@angular/core/testing'; import { DataService } from './data.service'; describe('DataService', () => { let service: DataService; beforeEach(() => { TestBed.configureTestingModule({}); service = TestBed.inject(DataService); }); it('should be created', () => { expect(service).toBeTruthy(); }); it('should return "Hello, Angular!" from getData', () => { expect(service.getData()).toBe('Hello, Angular!'); }); });
Explicació del codi
- TestBed.configureTestingModule: Configura un mòdul de proves per al servei.
- TestBed.inject: Obté una instància del servei.
- expect(service).toBeTruthy(): Verifica que el servei s'ha creat correctament.
- expect(service.getData()).toBe('Hello, Angular!'): Verifica que el mètode
getData
retorna el valor esperat.
- Utilitzar simulacions (mocks) per a les dependències dels serveis
Quan un servei depèn d'altres serveis, és important utilitzar simulacions per a aquestes dependències per aïllar les proves.
Exemple de servei amb dependències
Suposem que tenim un servei user.service.ts
que depèn d'un altre servei http.service.ts
:
import { Injectable } from '@angular/core'; import { HttpService } from './http.service'; @Injectable({ providedIn: 'root' }) export class UserService { constructor(private httpService: HttpService) { } getUser() { return this.httpService.get('/user'); } }
Exemple de fitxer de proves amb simulacions
A continuació, es mostra com escriure proves unitàries per al servei UserService
utilitzant simulacions per a HttpService
.
import { TestBed } from '@angular/core/testing'; import { UserService } from './user.service'; import { HttpService } from './http.service'; import { of } from 'rxjs'; describe('UserService', () => { let service: UserService; let httpServiceSpy: jasmine.SpyObj<HttpService>; beforeEach(() => { const spy = jasmine.createSpyObj('HttpService', ['get']); TestBed.configureTestingModule({ providers: [ UserService, { provide: HttpService, useValue: spy } ] }); service = TestBed.inject(UserService); httpServiceSpy = TestBed.inject(HttpService) as jasmine.SpyObj<HttpService>; }); it('should be created', () => { expect(service).toBeTruthy(); }); it('should return user data from getUser', (done: DoneFn) => { const expectedData = { name: 'John Doe' }; httpServiceSpy.get.and.returnValue(of(expectedData)); service.getUser().subscribe(data => { expect(data).toEqual(expectedData); done(); }); }); });
Explicació del codi
- jasmine.createSpyObj: Crea una simulació per a
HttpService
amb un mètodeget
. - providers: Proporciona la simulació en lloc de la implementació real de
HttpService
. - httpServiceSpy.get.and.returnValue(of(expectedData)): Configura la simulació per retornar dades esperades.
- done: Utilitzat per gestionar proves asincròniques.
Conclusió
En aquest tema, hem après la importància de les proves de serveis, com configurar l'entorn de proves, escriure proves unitàries per als serveis d'Angular i utilitzar simulacions per a les dependències dels serveis. Les proves de serveis són essencials per assegurar la fiabilitat i mantenibilitat de les aplicacions Angular.
Exercici pràctic
Crea un servei ProductService
que tingui un mètode getProducts
que retorni una llista de productes. Escriu proves unitàries per a aquest servei, assegurant-te d'utilitzar simulacions per a qualsevol dependència.
Solució
// product.service.ts import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class ProductService { constructor() { } getProducts() { return ['Product 1', 'Product 2', 'Product 3']; } }
// product.service.spec.ts import { TestBed } from '@angular/core/testing'; import { ProductService } from './product.service'; describe('ProductService', () => { let service: ProductService; beforeEach(() => { TestBed.configureTestingModule({}); service = TestBed.inject(ProductService); }); it('should be created', () => { expect(service).toBeTruthy(); }); it('should return a list of products from getProducts', () => { const products = service.getProducts(); expect(products).toEqual(['Product 1', 'Product 2', 'Product 3']); }); });
Amb això, has completat el tema sobre proves de serveis a Angular. Ara estàs preparat per escriure proves unitàries robustes per als teus serveis, assegurant la qualitat i fiabilitat del teu codi.
Curs d'Angular
Mòdul 1: Introducció a Angular
- Què és Angular?
- Configuració de l'entorn de desenvolupament
- Arquitectura d'Angular
- Primera aplicació Angular
Mòdul 2: Components d'Angular
- Comprendre els components
- Crear components
- Plantilles de components
- Estils de components
- Interacció de components
Mòdul 3: Enllaç de dades i directives
- Interpolació i enllaç de propietats
- Enllaç d'esdeveniments
- Enllaç de dades bidireccional
- Directives integrades
- Directives personalitzades
Mòdul 4: Serveis i injecció de dependències
Mòdul 5: Enrutament i navegació
Mòdul 6: Formularis a Angular
Mòdul 7: Client HTTP i observables
- Introducció al client HTTP
- Fer sol·licituds HTTP
- Gestionar respostes HTTP
- Utilitzar observables
- Gestió d'errors
Mòdul 8: Gestió d'estat
- Introducció a la gestió d'estat
- Utilitzar serveis per a la gestió d'estat
- NgRx Store
- NgRx Effects
- NgRx Entity
Mòdul 9: Proves a Angular
- Proves unitàries
- Proves de components
- Proves de serveis
- Proves de cap a cap
- Simulació de dependències
Mòdul 10: Conceptes avançats d'Angular
- Angular Universal
- Optimització del rendiment
- Internacionalització (i18n)
- Tubs personalitzats
- Animacions d'Angular