测试 HTTP 请求的请求和结果之间的条件
Test a condition between the request and result of a HTTP request
假设一个组件方法创建一个 HTTP GET 请求,在等待响应时设置加载状态,并在给出响应时删除加载状态。例如:
getData() {
this.myService
.getSomeDate()
.pipe(tap(_ => {
this.loading = true;
}))
.subscribe(result => {
this.data = result;
this.loading = false;
});
}
您将如何通过测试验证请求和响应之间的状态(例如 pipe
部分)确实正在加载?我尝试使用 HttpTestingController
发送 HttpEventType.Sent
事件,但似乎不起作用。调用 req.flush()
将导致代码立即转到 subscribe
部分,因此这也不起作用。这是我用过的测试方法:
it('should have a loading state durin the request', () => {
component.getData();
const req = httpClient.expectOne('http://localhost:8080');
req.event({type: HttpEventType.Sent});
expect(component.loading).toBe(true);
req.flush();
expect(component.loading).toBe(false);
});
备注
请注意 Observable.pipe
仅在结果值到达时调用。因此,在 getData
方法中,在调用 myService.getSomeDateservice
之前应将 loading
状态设置为 true
并且不需要 pipe
。
对component
进行单元测试时,应该mock相关的服务方法。
组件
getData() {
this.loading = true;
this.myService.getSomeDate()
.subscribe(result => {
this.data = result;
this.loading = false;
});
}
单元测试
现在您可以尝试 运行 在伪异步区域中进行测试(使用 fakeAsync
)并在两者之间使用 flush
exec
.
import { ComponentFixture, TestBed, fakeAsync, flush} from '@angular/core/testing';
import { Observable, of } from 'rxjs';
...
it('should have a loading state durin the request', fakeAsync(() => {
const myService = TestBed.get(MyService);
const data = ... // define data to be returned by myService.getSomeDate
spyOn(myService, 'getSomeDate').and.returnValue(of(data));
component.getData();
expect(component.loading).toBe(true);
flush();
expect(component.loading).toBe(false);
}));
更新
of
returns 同步传递作为参数提供的值的 Observable
。因此,上面的测试实际上并没有涉及异步代码。正如下面评论中 Andrei Gătej 所提到的,这使得 flush
变得毫无用处。通过pipe(delay(1))
,我们可以模拟异步处理,现在将使用tick
来模拟时间的异步流逝。
it('should have a loading state durin the request', fakeAsync(() => {
....
spyOn(myService, 'getSomeDate').and.returnValue(of(data).pipe(delay(1)));
component.getData();
expect(component.loading).toBe(true);
tick(1);
expect(component.loading).toBe(false);
}));
假设一个组件方法创建一个 HTTP GET 请求,在等待响应时设置加载状态,并在给出响应时删除加载状态。例如:
getData() {
this.myService
.getSomeDate()
.pipe(tap(_ => {
this.loading = true;
}))
.subscribe(result => {
this.data = result;
this.loading = false;
});
}
您将如何通过测试验证请求和响应之间的状态(例如 pipe
部分)确实正在加载?我尝试使用 HttpTestingController
发送 HttpEventType.Sent
事件,但似乎不起作用。调用 req.flush()
将导致代码立即转到 subscribe
部分,因此这也不起作用。这是我用过的测试方法:
it('should have a loading state durin the request', () => {
component.getData();
const req = httpClient.expectOne('http://localhost:8080');
req.event({type: HttpEventType.Sent});
expect(component.loading).toBe(true);
req.flush();
expect(component.loading).toBe(false);
});
备注
请注意
Observable.pipe
仅在结果值到达时调用。因此,在getData
方法中,在调用myService.getSomeDateservice
之前应将loading
状态设置为true
并且不需要pipe
。对
component
进行单元测试时,应该mock相关的服务方法。
组件
getData() {
this.loading = true;
this.myService.getSomeDate()
.subscribe(result => {
this.data = result;
this.loading = false;
});
}
单元测试
现在您可以尝试 运行 在伪异步区域中进行测试(使用 fakeAsync
)并在两者之间使用 flush
exec
.
import { ComponentFixture, TestBed, fakeAsync, flush} from '@angular/core/testing';
import { Observable, of } from 'rxjs';
...
it('should have a loading state durin the request', fakeAsync(() => {
const myService = TestBed.get(MyService);
const data = ... // define data to be returned by myService.getSomeDate
spyOn(myService, 'getSomeDate').and.returnValue(of(data));
component.getData();
expect(component.loading).toBe(true);
flush();
expect(component.loading).toBe(false);
}));
更新
of
returns 同步传递作为参数提供的值的 Observable
。因此,上面的测试实际上并没有涉及异步代码。正如下面评论中 Andrei Gătej 所提到的,这使得 flush
变得毫无用处。通过pipe(delay(1))
,我们可以模拟异步处理,现在将使用tick
来模拟时间的异步流逝。
it('should have a loading state durin the request', fakeAsync(() => {
....
spyOn(myService, 'getSomeDate').and.returnValue(of(data).pipe(delay(1)));
component.getData();
expect(component.loading).toBe(true);
tick(1);
expect(component.loading).toBe(false);
}));