Angular 中的单元测试 Http 调用
Unit Testing Http Calls in Angular
我正在使用 Angular 9+。
虽然 unit testing
服务实现 httpClient
并发出 http 请求,但我将此 documentation 推荐给 Angular 团队。我遵循了这个过程,并在单元测试中也取得了成功。
以下是代码(取自文档):
it('can test HttpClient.get', () => {
const testData: Data = {name: 'Test Data'};
// Make an HTTP GET request
httpClient.get<Data>(testUrl)
.subscribe(data =>
// When observable resolves, result should match test data
expect(data).toEqual(testData)
);
// The following `expectOne()` will match the request's URL.
// If no requests or multiple requests matched that URL
// `expectOne()` would throw.
const req = httpTestingController.expectOne('/data');
// Assert that the request is a GET.
expect(req.request.method).toEqual('GET');
// Respond with mock data, causing Observable to resolve.
// Subscribe callback asserts that correct data was returned.
req.flush(testData);
// Finally, assert that there are no outstanding requests.
httpTestingController.verify();
});
我的问题是:
既然http calls
是asynchronous
,为什么文档中提供的任何测试都没有写fakeAsync()?就像单元测试 asynchronous methods
( setTimeout() , setInterval()
) 一样,angular 中提供的文档表明我们需要一个伪造的 zone.js 附加所有对数组的异步请求,然后我们使用 flushMicrotasks() 或 tick() 来进一步促进调用。
调用 req.flush()
时控制流是如何发生的?我们已经调用了订阅可观察对象的函数 httpClient.get<Data>(testUrl)
,并且 flush 用于解析它。所以测试规范中的整个流程正在发生异步/同步?
rxjs 的性质允许您处理流而无需考虑它们是同步的还是异步的。为了测试 http 客户端,为了便于测试,事情是同步的。 httpClient 是以异步代码在测试中表现同步的方式制作的,因为每个“异步”工作都基于 rxjs 流。 streams api 足够强大来制作异步逻辑 - 在某些情况下是同步的。通过 js 世界中的异步,通常会提到在执行此代码之前,js 执行调用堆栈应该变为空
req.flush(...);
将在此行调用组件内部的订阅处理程序。在它之后你可以断言那个处理程序的结果
我正在使用 Angular 9+。
虽然 unit testing
服务实现 httpClient
并发出 http 请求,但我将此 documentation 推荐给 Angular 团队。我遵循了这个过程,并在单元测试中也取得了成功。
以下是代码(取自文档):
it('can test HttpClient.get', () => {
const testData: Data = {name: 'Test Data'};
// Make an HTTP GET request
httpClient.get<Data>(testUrl)
.subscribe(data =>
// When observable resolves, result should match test data
expect(data).toEqual(testData)
);
// The following `expectOne()` will match the request's URL.
// If no requests or multiple requests matched that URL
// `expectOne()` would throw.
const req = httpTestingController.expectOne('/data');
// Assert that the request is a GET.
expect(req.request.method).toEqual('GET');
// Respond with mock data, causing Observable to resolve.
// Subscribe callback asserts that correct data was returned.
req.flush(testData);
// Finally, assert that there are no outstanding requests.
httpTestingController.verify();
});
我的问题是:
既然
http calls
是asynchronous
,为什么文档中提供的任何测试都没有写fakeAsync()?就像单元测试asynchronous methods
(setTimeout() , setInterval()
) 一样,angular 中提供的文档表明我们需要一个伪造的 zone.js 附加所有对数组的异步请求,然后我们使用 flushMicrotasks() 或 tick() 来进一步促进调用。调用
req.flush()
时控制流是如何发生的?我们已经调用了订阅可观察对象的函数httpClient.get<Data>(testUrl)
,并且 flush 用于解析它。所以测试规范中的整个流程正在发生异步/同步?
rxjs 的性质允许您处理流而无需考虑它们是同步的还是异步的。为了测试 http 客户端,为了便于测试,事情是同步的。 httpClient 是以异步代码在测试中表现同步的方式制作的,因为每个“异步”工作都基于 rxjs 流。 streams api 足够强大来制作异步逻辑 - 在某些情况下是同步的。通过 js 世界中的异步,通常会提到在执行此代码之前,js 执行调用堆栈应该变为空
req.flush(...);
将在此行调用组件内部的订阅处理程序。在它之后你可以断言那个处理程序的结果