angular - 测试角度http拦截器-期望在拦截返回之前调用
问题描述
我有一个简单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))
到第二个测试中,它将起作用,但这是错误的。在第三次测试中这样做没有任何区别。
我希望有人可以向我解释这一点。
谢谢。
解决方案
我想这有助于重新(阅读)文档和源代码。我在想测试需要是异步的,因为正常的 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);
});
推荐阅读
- vue.js - 将输入值添加到对象中 (Vue.js)
- curl - 如何轮询资源 url 以获取文件更改
- android - 防止“强制关闭”和“卸载”
- javascript - Math.floor(x/y) 是确定性的吗?
- python - numpy where:在哪里添加值
- html - 使水平div中的多个斜线图像可点击
- botframework - 团队消息传递扩展是否可以返回纯文本响应而不是卡片?
- javascript - 你如何得到奇怪的表格并改变风格?
- javascript - 代理 ES6 类并维护原型链
- sparql - Querying property without value with SPARQL in WikiData