Appearance
Comment utiliser useClass dans Angular pour remplacer des services ?
Le provider useClass dans Angular permet de remplacer l'implémentation d'un service par une autre classe. C'est particulièrement utile pour les tests unitaires ou pour avoir différentes versions d'un même service.
Comprendre useClass avec un exemple concret
Imaginons que vous développez un site web comme Facebook. Vous avez deux situations :
En production : Le vrai site qui se connecte à la vraie base de données
- Les vrais utilisateurs
- Les vraies publications
- Les vrais commentaires
En développement/test : Une version "fausse" du site
- Des utilisateurs fictifs
- Des publications de test
- Des commentaires de démonstration
C'est exactement ce que permet useClass
: avoir deux versions du même service, mais n'en utiliser qu'une seule à la fois.
Différences avec les autres providers
Provider | Description | Exemple | Cas d'utilisation | Documentation |
---|---|---|---|---|
useClass | Remplace complètement un service par une autre classe | { provide: UserService, useClass: MockUserService } | Quand vous voulez une implémentation complètement différente (ex: mock pour les tests) | En savoir plus |
useValue | Fournit une valeur fixe | { provide: API_URL, useValue: 'https://api.example.com' } | Pour des constantes ou des objets simples prédéfinis | En savoir plus |
useFactory | Crée dynamiquement une valeur via une fonction | { provide: UserService, useFactory: () => environment.production ? new RealUserService() : new MockUserService() } | Quand la valeur dépend de conditions ou nécessite une logique de création | En savoir plus |
useExisting | Crée un alias vers un service existant | { provide: AbstractLogger, useExisting: ConsoleLogger } | Quand vous voulez utiliser un service existant sous un autre nom | En savoir plus |
Mise en pratique avec notre gestionnaire d'utilisateurs
Commençons par créer notre service de base pour gérer les utilisateurs :
ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { User } from './user';
import { Observable } from 'rxjs';
@Injectable()
export class UserService {
private http = inject(HttpClient);
private apiUrl = 'https://api.example.com/users';
getUsers(): Observable<User[]> {
return this.http.get<User[]>(this.apiUrl);
}
}
ts
import { Injectable } from '@angular/core';
import { User } from './user';
import { Observable, of } from 'rxjs';
@Injectable()
export class MockUserService extends UserService {
private mockUsers: User[] = [
{ id: 1, name: 'John Doe', username: 'john', email: '[email protected]' },
{ id: 2, name: 'Jane Doe', username: 'jane', email: '[email protected]' }
];
getUsers(): Observable<User[]> {
return of(this.mockUsers);
}
}
ts
export interface User {
id: number;
name: string;
username?: string;
email: string;
address?: {
street: string;
suite: string;
city: string;
zipcode: string;
geo: {
lat: string;
lng: string;
}
};
phone?: string;
website?: string;
company?: {
name: string;
catchPhrase: string;
bs: string;
};
}
CONSEIL
Il est recommandé de toujours étendre la classe originale lors de la création d'un mock. Cela garantit que toutes les méthodes sont bien implémentées.
Voici comment configurer le provider dans votre application :
ts
import { ApplicationConfig } from '@angular/core';
import { UserService } from './user.service';
import { MockUserService } from './mock-user.service';
export const appConfig: ApplicationConfig = {
providers: [
{
provide: UserService,
useClass: MockUserService
}
]
};
Imaginez que vous allez sur Facebook, mais au lieu d'avoir l'interface réelle de Facebook, vous tombez sur une version "fausse" qui ressemble à Facebook mais avec des données fictives. C'est exactement ce que fait useClass
!
Voici comment ça marche :
typescript
{
provide: UserService, // "Je veux aller sur Facebook"
useClass: MockUserService // "Mais montre-moi la version fausse à la place"
}
IMPORTANT
Tout comme un faux site doit avoir les mêmes fonctionnalités que le vrai (même si elles ne font pas la même chose), le MockUserService doit avoir les mêmes méthodes que le vrai UserService.
Cas d'utilisation typiques
Tests : Au lieu d'appeler une vraie API, on utilise des données fictives
- Comme tester un site e-commerce sans vraiment passer de commandes
Développement : Travailler sans connexion internet
- Comme développer un site qui utilise Twitter sans avoir besoin de vraiment se connecter à Twitter
Démonstration : Montrer une version du site avec des données de démo
- Comme présenter un réseau social avec des utilisateurs fictifs pour une démo
Cas d'utilisation courants
- Tests unitaires : Remplacer les services qui font des appels HTTP par des mocks
- Environnements différents : Avoir différentes implémentations pour le développement et la production
- Feature flags : Switcher entre différentes implémentations selon les fonctionnalités activées
BONNE PRATIQUE
Pour les tests unitaires, il est préférable de configurer useClass dans le TestBed plutôt que dans la configuration globale de l'application :
ts
TestBed.configureTestingModule({
providers: [
{
provide: UserService,
useClass: MockUserService
}
]
});