如何在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 主题页面 以获取练习和编程项目。