Angular 13 TestBed 没有注入拦截器
Angular 13 TestBed doesn't inject interceptor
我有一个带有自定义 HTTP 客户端和拦截器的 Angular 13 应用程序,我想对其进行单元测试。
base-url.interceptor.ts
:
import { Inject, Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
export const BASE_API_URL = 'BASE_API_URL';
@Injectable()
export class BaseUrlInterceptor implements HttpInterceptor {
constructor(@Inject(BASE_API_URL) private baseUrl: string) {}
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
const apiRequest = request.clone({ url: `${this.baseUrl}${request.url}` });
return next.handle(apiRequest);
}
}
base-url.interceptor.spec.ts
:
import { TestBed } from '@angular/core/testing';
import { ApiHttpService, API_HTTP_INTERCEPTORS } from '../api-http.service';
import { BaseUrlInterceptor, BASE_API_URL } from './base-url.interceptor';
describe('BaseUrlInterceptor', () => {
let interceptor: BaseUrlInterceptor;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
providers: [
ApiHttpService,
{ provide: BASE_API_URL, value: 'http://example.com' },
{ provide: API_HTTP_INTERCEPTORS, useClass: BaseUrlInterceptor, multi: true }
]
});
interceptor = TestBed.inject(BaseUrlInterceptor);
});
it('should be created', () => {
expect(interceptor).toBeTruthy();
});
});
不幸的是TestBed.inject(BaseUrlInterceptor)
未能注入拦截器实例。 interceptor
总是 undefined
。如果我通过手动创建实例来解决这个问题 new BaseUrlInterceptor('http://example.com');
它可以工作,但其他拦截器有进一步的依赖关系,我想在这里使用 Angulars 依赖注入。
如何配置 TestBed,使其能够成功创建 BaseUrlInterceptor
的实例?
我创建了一个最小的 CodeSandbox 重现了这个问题:
https://codesandbox.io/s/snowy-dust-t964no?file=/src/app/base-url.interceptor.spec.ts
此外,当我 运行 错误测试时,我收到此错误消息:
Chrome Headless 98.0.4758.102 (Linux x86_64) BaseUrlInterceptor should be created FAILED
Error: NG0204: unreachable
error properties: Object({ code: 204 })
Error: NG0204: unreachable
at injectableDefOrInjectorDefFactory (node_modules/@angular/core/fesm2015/core.mjs:11494:1)
at providerToFactory (node_modules/@angular/core/fesm2015/core.mjs:11556:1)
at providerToRecord (node_modules/@angular/core/fesm2015/core.mjs:11521:1)
at R3Injector.processProvider (node_modules/@angular/core/fesm2015/core.mjs:11424:1)
at node_modules/@angular/core/fesm2015/core.mjs:11410:1
at node_modules/@angular/core/fesm2015/core.mjs:4162:1
at Array.forEach (<anonymous>)
at deepForEach (node_modules/@angular/core/fesm2015/core.mjs:4162:1)
at R3Injector.processInjectorType (node_modules/@angular/core/fesm2015/core.mjs:11410:1)
at node_modules/@angular/core/fesm2015/core.mjs:11213:1
Error: Expected undefined to be truthy.
at <Jasmine>
at UserContext.<anonymous> (projects/frontend/src/app/core/http/interceptors/base-url.interceptor.spec.ts:21:25)
at ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:372:1)
at ProxyZoneSpec.onInvoke (node_modules/zone.js/fesm2015/zone-testing.js:287:1)
Chrome Headless 98.0.4758.102 (Linux x86_64): Executed 1 of 1 (1 FAILED) (0.072 secs / 0.056 secs)
TOTAL: 1 FAILED, 0 SUCCESS
您得到 Error: NG0204: unreachable
是因为当您为 BASE_API_URL
定义提供程序时,您使用的是 属性 value
而它应该是 [=16] =].
{ provide: BASE_API_URL, useValue: 'http://example.com' },
无论如何,即使您修复了该问题,您也会得到一个 NullInjectorError
,因为您没有定义使用 BaseUrlInterceptor
class 作为 InjectionToken 的提供程序。您正在使用 class 作为 API_HTTP_INTERCEPTORS
令牌的提供者之一。
在对拦截器进行单元测试的上下文中,您应该摆脱 ApiHttpService,而只关注拦截器 class。
您有两个选择:
手动实例化class
beforeEach(() => {
interceptor = new BaseUrlInterceptor('http://example.com');
});
或者在 Testbed
中使用拦截器 class 作为提供者
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
providers: [
{ provide: BASE_API_URL, useValue: 'http://example.com' },
BaseUrlInterceptor,
],
});
interceptor = TestBed.inject(BaseUrlInterceptor);
});
干杯
我有一个带有自定义 HTTP 客户端和拦截器的 Angular 13 应用程序,我想对其进行单元测试。
base-url.interceptor.ts
:
import { Inject, Injectable } from '@angular/core';
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';
export const BASE_API_URL = 'BASE_API_URL';
@Injectable()
export class BaseUrlInterceptor implements HttpInterceptor {
constructor(@Inject(BASE_API_URL) private baseUrl: string) {}
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
const apiRequest = request.clone({ url: `${this.baseUrl}${request.url}` });
return next.handle(apiRequest);
}
}
base-url.interceptor.spec.ts
:
import { TestBed } from '@angular/core/testing';
import { ApiHttpService, API_HTTP_INTERCEPTORS } from '../api-http.service';
import { BaseUrlInterceptor, BASE_API_URL } from './base-url.interceptor';
describe('BaseUrlInterceptor', () => {
let interceptor: BaseUrlInterceptor;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
providers: [
ApiHttpService,
{ provide: BASE_API_URL, value: 'http://example.com' },
{ provide: API_HTTP_INTERCEPTORS, useClass: BaseUrlInterceptor, multi: true }
]
});
interceptor = TestBed.inject(BaseUrlInterceptor);
});
it('should be created', () => {
expect(interceptor).toBeTruthy();
});
});
不幸的是TestBed.inject(BaseUrlInterceptor)
未能注入拦截器实例。 interceptor
总是 undefined
。如果我通过手动创建实例来解决这个问题 new BaseUrlInterceptor('http://example.com');
它可以工作,但其他拦截器有进一步的依赖关系,我想在这里使用 Angulars 依赖注入。
如何配置 TestBed,使其能够成功创建 BaseUrlInterceptor
的实例?
我创建了一个最小的 CodeSandbox 重现了这个问题: https://codesandbox.io/s/snowy-dust-t964no?file=/src/app/base-url.interceptor.spec.ts
此外,当我 运行 错误测试时,我收到此错误消息:
Chrome Headless 98.0.4758.102 (Linux x86_64) BaseUrlInterceptor should be created FAILED
Error: NG0204: unreachable
error properties: Object({ code: 204 })
Error: NG0204: unreachable
at injectableDefOrInjectorDefFactory (node_modules/@angular/core/fesm2015/core.mjs:11494:1)
at providerToFactory (node_modules/@angular/core/fesm2015/core.mjs:11556:1)
at providerToRecord (node_modules/@angular/core/fesm2015/core.mjs:11521:1)
at R3Injector.processProvider (node_modules/@angular/core/fesm2015/core.mjs:11424:1)
at node_modules/@angular/core/fesm2015/core.mjs:11410:1
at node_modules/@angular/core/fesm2015/core.mjs:4162:1
at Array.forEach (<anonymous>)
at deepForEach (node_modules/@angular/core/fesm2015/core.mjs:4162:1)
at R3Injector.processInjectorType (node_modules/@angular/core/fesm2015/core.mjs:11410:1)
at node_modules/@angular/core/fesm2015/core.mjs:11213:1
Error: Expected undefined to be truthy.
at <Jasmine>
at UserContext.<anonymous> (projects/frontend/src/app/core/http/interceptors/base-url.interceptor.spec.ts:21:25)
at ZoneDelegate.invoke (node_modules/zone.js/fesm2015/zone.js:372:1)
at ProxyZoneSpec.onInvoke (node_modules/zone.js/fesm2015/zone-testing.js:287:1)
Chrome Headless 98.0.4758.102 (Linux x86_64): Executed 1 of 1 (1 FAILED) (0.072 secs / 0.056 secs)
TOTAL: 1 FAILED, 0 SUCCESS
您得到 Error: NG0204: unreachable
是因为当您为 BASE_API_URL
定义提供程序时,您使用的是 属性 value
而它应该是 [=16] =].
{ provide: BASE_API_URL, useValue: 'http://example.com' },
无论如何,即使您修复了该问题,您也会得到一个 NullInjectorError
,因为您没有定义使用 BaseUrlInterceptor
class 作为 InjectionToken 的提供程序。您正在使用 class 作为 API_HTTP_INTERCEPTORS
令牌的提供者之一。
在对拦截器进行单元测试的上下文中,您应该摆脱 ApiHttpService,而只关注拦截器 class。
您有两个选择:
手动实例化class
beforeEach(() => {
interceptor = new BaseUrlInterceptor('http://example.com');
});
或者在 Testbed
中使用拦截器 class 作为提供者beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
providers: [
{ provide: BASE_API_URL, useValue: 'http://example.com' },
BaseUrlInterceptor,
],
});
interceptor = TestBed.inject(BaseUrlInterceptor);
});
干杯