如何在Angular中测试HttpClient请求
介绍
Angular 的 HttpClient 有一个测试模块,HttpClientTestingModule,它可以让你对 HTTP 请求进行单元测试。
注意: 由于 HttpClient
仅从 Angular 4.3 开始可用,以下适用于 Angular 4.3+。 如果您不熟悉 Angular 中的单元测试,请参阅 这个介绍。
在本文中,您将学习如何使用 HttpClientTestingModule
为 HTTP GET 请求设置单元测试。 这将有助于展示测试模块的功能。
先决条件
要完成本教程,您需要:
- Node.js 安装在本地,您可以按照【X57X】如何安装Node.js 并创建本地开发环境【X126X】进行。
- 熟悉 设置 Angular 项目 。
本教程已使用 Node v16.2.0、npm
v7.15.1 和 @angular/core
v12.0.4 进行了验证。
第 1 步 — 设置项目
对于这篇文章,我们将使用从端点获取数据的服务和调用该服务以填充组件的 OnInit
挂钩中的用户列表的组件。
您可以使用 @angular/cli
创建一个新项目:
ng new angular-httpclienttest-example
然后,导航到新创建的项目目录:
cd angular-httpclienttest-example
创建一个 data.service.ts
:
ng generate service data
并让它与 JSON 占位符通信:
src/app/data.service.ts
import { Injectable } from '@angular/core'; import { HttpClient, HttpRequest } from '@angular/common/http'; @Injectable({ ... }) export class DataService { url = 'https://jsonplaceholder.typicode.com/users'; constructor(private http: HttpClient) { } getData() { const req = new HttpRequest('GET', this.url, { reportProgress: true }); return this.http.request(req); } }
然后,修改app.component.ts
文件:
src/app.component.ts
import { Component, OnInit } from '@angular/core'; import { HttpEvent, HttpEventType } from '@angular/common/http'; import { DataService } from './data.service'; @Component({ ... }) export class AppComponent implements OnInit { users: any; constructor(private dataService: DataService) {} ngOnInit() { this.populateUsers(); } private populateUsers() { this.dataService.getData().subscribe((event: HttpEvent<any>) => { switch (event.type) { case HttpEventType.Sent: console.log('Request sent!'); break; case HttpEventType.ResponseHeader: console.log('Response header received!'); break; case HttpEventType.DownloadProgress: const kbLoaded = Math.round(event.loaded / 1024); console.log(`Download in progress! ${kbLoaded}Kb loaded`); break; case HttpEventType.Response: console.log('Done!', event.body); this.users = event.body; } }); } }
并将 HttpClientmodule
添加到 app.module.ts
:
src/app.module.ts
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { HttpClientModule } from '@angular/common/http'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, HttpClientModule ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
此时,您将拥有一个带有服务和客户端的 Angular 项目。
第 2 步 — 添加测试
现在我们将为我们的数据服务设置一个规范文件,并包含必要的实用程序来测试 HttpClient
请求。 在 HttpClientTestingModule
之上,我们还需要 HttpTestingController
,这使得模拟请求变得容易:
data.service.spec.ts
import { TestBed, inject } from '@angular/core/testing'; import { HttpEvent, HttpEventType } from '@angular/common/http'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { DataService } from './data.service'; describe('DataService', () => { let service: DataService; beforeEach(() => { TestBed.configureTestingModule({} imports: [HttpclientTestingModule], providers: [DataService] ); service = TestBed.inject(DataService); }); });
我们使用 inject
实用程序将所需的服务注入到我们的测试中。
有了这个,我们可以添加我们的测试逻辑:
data.service.spec.ts
import { TestBed, inject } from '@angular/core/testing'; import { HttpEvent, HttpEventType } from '@angular/common/http'; import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; import { DataService } from './data.service'; describe('DataService', () => { beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule], providers: [DataService] }); }); it( 'should get users', inject( [HttpTestingController, DataService], (httpMock: HttpTestingController, dataService: DataService) => { const mockUsers = [ { name: 'Alice', website: 'example.com' }, { name: 'Bob', website: 'example.org' } ]; dataService.getData().subscribe((event: HttpEvent<any>) => { switch (event.type) { case HttpEventType.Response: expect(event.body).toEqual(mockUsers); } }); const mockReq = httpMock.expectOne(dataService.url); expect(mockReq.cancelled).toBeFalsy(); expect(mockReq.request.responseType).toEqual('json'); mockReq.flush(mockUsers); httpMock.verify(); } ) ); });
发生了很多事情,所以让我们分解一下:
- 首先,我们定义了几个我们将对其进行测试的模拟用户。
- 然后我们在我们正在测试的服务中调用
getData
方法并订阅返回的 observable。 - 如果
HttpEventType
是Response
类型,我们断言响应事件的主体等于我们的模拟用户。 - 然后,我们使用
HttpTestingController
(在测试中作为httpMock
注入)来断言对服务的url
属性发出了一个请求。 如果没有请求,也可以使用expectNone
方法。 - 我们现在可以对模拟请求进行任意数量的断言。 这里我们断言请求没有被取消并且响应的类型是
json
。 此外,我们可以断言请求的方法 (GET
,POST
, ...) - 接下来,我们在模拟请求上调用
flush
并传入我们的模拟用户。flush
方法使用传递给它的数据完成请求。 - 最后,我们在
HttpTestingController
实例上调用verify
方法,以确保没有未完成的请求。
出于本教程的目的,您可以注释掉 app.component.spec.ts
。
通过运行以下命令查看测试结果:
ng test
在浏览器中打开测试结果:
Output1 spec, 0 failures, randomized with seed 26321 DataService should get users
它将显示成功的测试消息。
结论
在本文中,您学习了如何使用 HttpClientTestingModule
为 HTTP GET 请求设置单元测试。
如果您想了解有关 Angular 的更多信息,请查看 我们的 Angular 主题页面 以获取练习和编程项目。