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:

ng test

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

  1. Importacions: Importem les funcions necessàries de @angular/core/testing i el component que volem provar.
  2. Descripció de la prova: Utilitzem describe per agrupar les proves relacionades amb HelloComponent.
  3. Configuració del TestBed: TestBed és una utilitat d'Angular per configurar i inicialitzar l'entorn de proves. Aquí, declarem el component que volem provar.
  4. Creació del component: Utilitzem TestBed.createComponent per crear una instància del component i assignar-la a fixture i component.
  5. 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

  1. Mock del servei: Creem una classe MockGreetingService que simula el comportament del servei real.
  2. Proveïdors: En la configuració del TestBed, utilitzem providers per substituir el servei real pel mock.
  3. 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ó

  1. Creació del component: El component CounterComponent té una propietat count i un mètode increment que incrementa el comptador.
  2. 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

Mòdul 2: Conceptes bàsics de TypeScript

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

Mòdul 9: Gestió d'estat

Mòdul 10: Proves en Angular

Mòdul 11: Temes avançats

Mòdul 12: Desplegament i millors pràctiques

© Copyright 2024. Tots els drets reservats