Services de tests en angulaire

Découvrez comment tester un service dans Angular et assurez-vous qu’il interagit avec les API. Vérifiez l’appel API et renvoyez les données.
Lorsque nous construisons des applications avec Angular, les composants ont la responsabilité d’afficher les données et de permettre l’interaction de l’utilisateur. Dans certains cas, les données proviennent de services sous forme de données statiques ou, dans le monde réel, d’une API.
Dans le article précédent, nous avons appris à tester nos composants en nous moquant de fausses données. Cependant, l’application ne se limite pas à ses composants : qu’en est-il du service ?
Aujourd’hui, nous allons apprendre à tester nos services afin qu’ils interagissent avec les API. Nous apprendrons comment nous assurer qu’ils appellent l’API et renvoient les données.
Allons-y !
Mise en place du projet
Tout d’abord, clonez le projet en exécutant la commande suivante dans le terminal :
git clone https://github.com/danywalls/testing-kendo-store.git
Cloning into 'testing-kendo-store'...
remote: Enumerating objects: 149, done.
remote: Counting objects: 100% (149/149), done.
remote: Compressing objects: 100% (90/90), done.
remote: Total 149 (delta 86), reused 115 (delta 54), pack-reused 0
Receiving objects: 93% (139/149
Receiving objects: 95% (142/149)
Receiving objects: 100% (149/149), 158.84 KiB | 2.24 MiB/s, done.
Resolving deltas: 100% (86/86), done.
Ensuite, installez toutes les dépendances du projet en exécutant npm install
dans le testing-kendo-store
annuaire.
cd testing-kendostore
npm i
added 1120 packages, and audited 1121 packages in 6s
133 packages are looking for funding
run `npm fund` for details
found 0 vulnerabilities
Exécutez la commande npm run test
pour confirmer que tout fonctionne.
Output location: C:\Users\DPAREDES\Desktop\articles\testing-kendo-store\dist\test-out
Application bundle generation complete. [1.294 seconds]
dist\test-out\browser\app.component.spec.js:
🚧 Browser logs:
Tests passed!
Chrome: |██████████████████████████████| 1/1 test files | 1 passed, 0 failed
Finished running tests in 0.8s, all tests passed! 🎉
Tester le service
Les services sont faciles à tester. Ce sont des classes avec ou sans dépendances. Semblable aux composants, nous pouvons compter sur TestBed
pour gérer le service et ses dépendances.
Testbed nous permet de fournir les dépendances. Angular fournit également d’autres utilitaires pour simplifier, comme HttpTestingController
et provideHttpClientTesting
pour faciliter les tests et les requêtes moqueuses.
En savoir plus sur HttpTestingController.
Avant de commencer, analysons notre code. Ouvrez le product.service.ts
. Nous avons une propriété pour faire la requête à l’API et exposer le products$
observable.
@Injectable({
providedIn: 'root'
})
export class ProductsService {
private API = 'https://fakestoreapi.com/products'
private http = inject(HttpClient)
public products$ = this.http.get<Product[]>(this.API);
}
Le product.service.ts
a besoin du httpClient
. De plus, il possède une propriété privée API
pointant vers l’API, nous devons donc nous assurer qu’il appelle l’API avec une requête GET.
Il faut configurer le TestBed
avec les points suivants :
- Fournir une simulation pour le
HttpClient
. - Utilisez le
HttpTestingController
pour se moquer de la réponse. - Réutilisez le
MOCK_PRODUCTS
exemples de données.
Commençons!
N’oubliez pas que nous avons expliqué les bases de Jasmine dans le article précédent.
Écrire le test
Ouvrez le products.service.spec.ts
il contient le code suivant qui ne ressemble pas à un vrai test :
describe('ProductsService', () => {
it('should be create in next article 🤣', () => {
expect(true).toBeTruthy();
});
});
Il est temps d’écrire le test pour notre ProductService
dans le products.service.spec.ts
fichier donc nous allons faire la même approche, déclarer deux variables pour le productService
et httpTestingController
.
import {ProductsService} from "./products.service";
import {HttpTestingController} from "@angular/common/http/testing";
describe('ProductsService', () => {
let productService: ProductsService;
let httpTestingController: HttpTestingController;
});
Ensuite, en utilisant le beforeEach
crochet de cycle de vie et utilisation Testbed
nous fournissons le provideHttpClient
, provideHttpClientTesting
et ProductService
.
Parce que le Testbed
s’occupe de la DI, on utilise TestBed.inject()
pour régler le httpTestingController
et ProductService
.
import {ProductsService} from "./products.service";
import {HttpTestingController, provideHttpClientTesting} from "@angular/common/http/testing";
import {TestBed} from "@angular/core/testing";
import {provideHttpClient} from "@angular/common/http";
describe('ProductsService ', () => {
let productService: ProductsService;
let httpTestingController: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule(
{
providers: [
provideHttpClient(),
provideHttpClientTesting(),
ProductsService,
],
}
)
productService = TestBed.inject(ProductsService);
httpTestingController = TestBed.inject(HttpTestingController);
});
});
Ensuite, écrivez un test pour valider que nous avons une instance de ProductService
.
it('should create an instance', () => {
expect(productService).toBeTruthy();
})
Refaites le test et c’est parfait ! 🎉
Application bundle generation complete. [1.258 seconds]
dist\test-out\browser\products.service.spec.js:
🚧 Browser logs:
Tests passed!
dist\test-out\browser\app.component.spec.js:
🚧 Browser logs:
Tests passed!
Chrome: |██████████████████████████████| 2/2 test files | 2 passed, 0 failed
Finished running tests in 0.9s, all tests passed! 🎉
OK, nous avons notre test de base pour créer une instance de ProductService
, mais cela n’ajoute pas vraiment beaucoup de valeur. je veux vérifier ça $products
renvoie une liste d’observables depuis le HTTP sans demander la véritable API.
Écrivons un vrai test où nous vérifions les données de la requête à l’aide d’un GET
demander et renvoyer un exemple fictif.
Test des requêtes HTTP
Testons notre service. Tout d’abord, ajoutez un nouveau test comme should make an HTTP request
. Notre test utilise le products$
propriété observable et souscrit à l’observable.
A l’intérieur, nous utilisons le matcher Jasmine expect
et toEqual
pour confirmer que la réponse est égale à MOCK_PRODUCTS
.
it('should make an HTTP request', fakeAsync (() => {
productService.products$.subscribe((response) => {
expect(response).toEqual(MOCK_PRODUCTS)
})
}
Parce que le httpTestingController
est à l’écoute de la demande, nous nous attendons à ce qu’il appelle le https://fakestoreapi.com/products
URL. Ainsi, nous appelons le expectOne
méthode et stocker la requête dans la variable req
puis appelez le httpTestingController.verify()
méthode pour confirmer que la demande concernait l’URL attendue.
const req = httpTestingController.expectOne('https://fakestoreapi.com/products');
httpTestingController.verify();
Enfin, nous confirmons que la demande est une GET
et videz les données de l’exemple fictif.
expect(req.request.method).toBe('GET');
req.flush(MOCK_PRODUCTS)
flush()
Le code final ressemble à :
import { fakeAsync, flush, TestBed } from '@angular/core/testing';
import { MOCK_PRODUCTS } from '../tests/mock';
...
it('should make an HTTP request', fakeAsync(() => {
productService.products$.subscribe((response) => {
expect(response).toEqual(MOCK_PRODUCTS);
});
const req = httpTestingController.expectOne(
'https://fakestoreapi.com/products',
);
httpTestingController.verify();
expect(req.request.method).toBe('GET');
req.flush(MOCK_PRODUCTS);
flush();
}));
Enregistrez les modifications et réexécutez vos tests et tada !! 🎉
Output location: C:\Users\DPAREDES\Desktop\articles\testing-kendo-store\dist\test-out
Application bundle generation complete. [1.220 seconds]
dist\test-out\browser\products.service.spec.js:
🚧 Browser logs:
Tests passed!
dist\test-out\browser\app.component.spec.js:
🚧 Browser logs:
Tests passed!
Chrome: |██████████████████████████████| 2/2 test files | 4 passed, 0 failed
Finished running tests in 0.9s, all tests passed! 🎉
Oui, nous avons notre application avec des tests pour les deux nos composants et services !! Je peux être tranquille ou apporter de nouvelles modifications dans l’application.
Qu’en est-il des tests d’interactions utilisateur ? 🤔
Oui, c’est une bonne question. Et si je souhaite tester une interaction ? Par exemple, lorsque l’utilisateur clique sur l’article, le bouton d’achat apparaît ?
Eh bien, c’est le moment où nous devons approfondir notre connaissance de Jasmine et utiliser les sélecteurs CSS pour interroger des éléments, ou nous pouvons utiliser des bibliothèques comme Bibliothèque de tests angulaires. Alternativement, une alternative simple mais puissante consiste à utiliser Progress Studio de test Telerik.
Telerik Test Studio permet de vérifier facilement que les applications exécutées dans un navigateur Web se comportent comme prévu sur différents navigateurs et simplifie l’observation d’une interface utilisateur Web cohérente sur plusieurs navigateurs ou versions de navigateur, pour des interactions utilisateur claires, une validation de formulaire, des appels d’API et bien plus encore.
Visitez les progrès Telerik DevCraft page pour en savoir plus sur les options groupées qui incluent Test Studio et Interface utilisateur Kendo pour angulaire.
Conclusion
Nous avons appris à quel point il est facile de tester notre service et comment TestBed nous aide à configurer les dépendances, nous enregistrons les dépendances sur TestBed et il gère DI pour nous fournir des instances.
Nous avons joué avec le HttpTestingController
, ce qui nous aide à nous moquer de la réponse et à éviter de passer des appels au serveur réel. Nous pouvons tester efficacement la logique du service sans compter sur des dépendances externes.
J’espère que cet article vous aidera à démarrer les tests dans Angular. Si vous voulez plus d’articles comme celui-ci, laissez un commentaire 👍🏼 !
Source link