我有一个简单的HttpInterceptor
用于设置加载状态。这是代码
@Injectable({
providedIn: 'root',
})
export class LoaderHttpInterceptor implements HttpInterceptor {
constructor(private _loadingService: LoadingService) {}
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
const id = uuid();
this._loadingService.startLoading(id);
return next
.handle(req)
.pipe(finalize(() => this._loadingService.completeLoading(id)));
}
}
这些是测试
describe('LoaderHttpInterceptor', () => {
let mockLoadingService: LoadingService;
let injector: Injector;
let httpClient: HttpClient;
let controller: HttpTestingController;
beforeEach(() => {
injector = TestBed.configureTestingModule({
imports: [TestingModule],
providers: [
{
provide: LoadingService,
useValue: { startLoading: jest.fn(), completeLoading: jest.fn() },
},
{
provide: HTTP_INTERCEPTORS,
useClass: LoaderHttpInterceptor,
multi: true,
deps: [LoadingService],
},
],
});
mockLoadingService = TestBed.get(LoadingService);
httpClient = TestBed.get(HttpClient);
controller = TestBed.get(HttpTestingController);
});
describe('intercept', () => {
it('should call loader service startLoading', () => {
const url = faker.internet.url();
httpClient.get(url, { responseType: 'text' }).subscribe(() => {
expect(mockLoadingService.startLoading).toBeCalledTimes(1);
});
controller.expectOne(url).flush('');
});
it('should call loader service completeLoading on success', async(() => {
const url = faker.internet.url();
httpClient.get(url, { responseType: 'text' })
.subscribe(() => {
expect(mockLoadingService.completeLoading).toBeCalledTimes(1);
});
controller.expectOne(url).flush({}, { status: 200, statusText: ''} );
controller.verify();
}));
it('should call loader service completeLoading on error', async(() => {
const url = faker.internet.url();
httpClient.get(url)
.subscribe(
() => {},
() => {
expect(mockLoadingService.completeLoading).toBeCalledTimes(1);
});
controller.expectOne(url).error(new ErrorEvent(faker.random.words(3)), {
status: 500
});
controller.verify();
}));
});
});
在最后两个测试中,测试中的expect
语句在拦截器中的finalize
运算符之前被调用,我不知道为什么。我的印象是,直到拦截器完成,http调用才返回。
如果我将pipe(delay(1000))
添加到第二个测试中,它将起作用,但这是错误的。在第三次测试中这样做没有区别。
我希望有人可以向我解释一下。
谢谢。
答案 0 :(得分:0)
我想这有助于重新(阅读)文档和源代码。我在想测试必须是异步的,因为普通的http请求是异步的,但是HttpTestingController
是同步发出的。测试需要这样写:
it('should call loader service completeLoading on success', () => {
const url = faker.internet.url();
httpClient.get(url, { responseType: 'text' }).subscribe();
controller.expectOne(url).flush({}, { status: 200, statusText: ''} );
controller.verify();
expect(mockLoadingService.completeLoading).toBeCalledTimes(1);
});