Aller au contenu

Lab 22 : Tests unitaires avec Vitest

album-wholesale-v17-signal-pre-jest

Dans ce lab, vous écrirez des tests unitaires pour les services et les composants en utilisant Vitest, le test runner moderne recommandé pour Angular. Vous utiliserez vi.fn() pour les mocks, les matchers Vitest et les hooks de cycle de vie.

Installez les versions compatibles manuellement (ng add @angular/vitest installe Vitest 4.x qui est incompatible avec Angular 17 / Vite 5) :

Fenêtre de terminal
npm install --save-dev vitest@2 @vitest/coverage-v8@2 @analogjs/vite-plugin-angular jsdom

Créez vite.config.ts à la racine du projet :

import { defineConfig } from 'vitest/config';
import angular from '@analogjs/vite-plugin-angular';
export default defineConfig({
plugins: [angular()],
test: {
globals: true,
environment: 'jsdom',
include: ['**/*.spec.ts'],
coverage: {
provider: 'v8',
reporter: ['text', 'html'],
},
},
});

Ajoutez un script de test dans package.json :

{
"scripts": {
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage"
}
}
Fenêtre de terminal
npm test

Vérifiez que tous les tests existants passent avant d’en ajouter de nouveaux.

Créez src/app/services/album.service.spec.ts :

import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController }
from '@angular/common/http/testing';
import { AlbumService } from './album.service';
import { Album } from '../model/album.model';
describe('AlbumService', () => {
let service: AlbumService;
let httpMock: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],
providers: [AlbumService],
});
service = TestBed.inject(AlbumService);
httpMock = TestBed.inject(HttpTestingController);
});
afterEach(() => httpMock.verify());
it('should fetch albums', () => {
const mockAlbums: Album[] = [
{ id: 1, name: 'Test Album', artist: 'Artist', price: 9, description: '', tags: [] },
];
service.findAll().subscribe(albums => {
expect(albums).toHaveLength(1);
expect(albums[0].name).toBe('Test Album');
});
const req = httpMock.expectOne('http://localhost:3000/albums');
expect(req.request.method).toBe('GET');
req.flush(mockAlbums);
});
});

Étape 4 : Utiliser vi.fn() pour mocker une dépendance

Section intitulée « Étape 4 : Utiliser vi.fn() pour mocker une dépendance »

Créez src/app/components/album-list/album-list.component.spec.ts :

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { vi } from 'vitest';
import { of } from 'rxjs';
import { AlbumListComponent } from './album-list.component';
import { AlbumService } from '../../services/album.service';
describe('AlbumListComponent', () => {
let fixture: ComponentFixture<AlbumListComponent>;
let albumServiceMock: { findAll: ReturnType<typeof vi.fn> };
beforeEach(async () => {
albumServiceMock = {
findAll: vi.fn().mockReturnValue(of([
{ id: 1, name: 'Mock Album', artist: 'Mock Artist', price: 9, description: '', tags: [] },
])),
};
await TestBed.configureTestingModule({
imports: [AlbumListComponent],
providers: [
{ provide: AlbumService, useValue: albumServiceMock },
],
}).compileComponents();
fixture = TestBed.createComponent(AlbumListComponent);
fixture.detectChanges();
});
it('should display albums', () => {
const items = fixture.nativeElement.querySelectorAll('.album-card');
expect(items.length).toBeGreaterThan(0);
});
it('should call findAll on init', () => {
expect(albumServiceMock.findAll).toHaveBeenCalledOnce();
});
});

Vitest fournit beforeAll, beforeEach, afterEach, afterAll :

describe('Calculs du panier', () => {
let items: CartItem[];
beforeEach(() => {
items = [
{ id: 1, quantity: 2, price: 10 },
{ id: 2, quantity: 1, price: 20 },
];
});
it('should calculate total', () => {
const total = items.reduce((sum, i) => sum + i.quantity * i.price, 0);
expect(total).toBe(40);
});
it('should count items', () => {
expect(items).toHaveLength(2);
});
});
Fenêtre de terminal
npm run test:coverage

Consultez le rapport de couverture et assurez-vous que les méthodes critiques des services sont couvertes.

Fenêtre de terminal
npx vitest --ui

Explorez le navigateur de tests interactif pour naviguer dans les tests et voir les résultats en temps réel.