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.

  1. 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.

  1. 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.

ng new my-angular-app
cd my-angular-app
ng test

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.

  1. 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.

  1. 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ètode get.
  • 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

Mòdul 2: Components d'Angular

Mòdul 3: Enllaç de dades i directives

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

Mòdul 8: Gestió d'estat

Mòdul 9: Proves a Angular

Mòdul 10: Conceptes avançats d'Angular

Mòdul 11: Desplegament i millors pràctiques

© Copyright 2024. Tots els drets reservats