Angular - 使用 Jasmine 监视 HttpClient 中的链式方法
Angular - Use Jasmine to spy on chained methods within HttpClient
我有一种情况需要监视在调用另一个方法之后调用的方法。
这是正在测试的 class/method:
@Injectable()
export class SomeService {
constructor(private customHttpClient: CustomHttpClient) {
}
updateSomethingCool(signerVO: SignerVO): Observable<SignerVO> {
// ...
return this.customHttpClient.withCustomOverrides(new CustomErrorHandlerHttpInterceptorOverride({ passthroughStatusCodes: [BAD_REQUEST, BAD_GATEWAY] }))
.put<SignerVO>(`/my/url/goes/here`, signerVO);
}
}
此 class 使用 CustomHttpClient,如下所示:
@Injectable()
export class CustomHttpClient extends HttpClient {
private interceptors: HttpInterceptor[] | null = null;
constructor(private injector: Injector,
originalHandler: HttpHandler, private originalBackend: HttpBackend) {
super(originalHandler);
}
public withCustomOverrides(...overrides: CustomHttpInterceptorOverride[]): HttpClient {
// do very customizable things here
return new CustomDelegatingHttpClient(
new CustomHttpInterceptingHandler(this.originalBackend, this.interceptors, overrides));
}
}
export class CustomDelegatingHttpClient extends HttpClient {
constructor(private delegate: HttpHandler) {
super(delegate);
}
}
这是我的单元测试尝试,确实调用了 put
方法,因此我需要监视 put
方法:
describe(SomeService.name, () => {
let service: SomeService;
let customHttpClient: CustomHttpClient;
let emptySignerVO: SignerVO = new SignerVO();
beforeEach(() => {
customHttpClient= <CustomHttpClient>{};
customHttpClient.put = () => null;
customHttpClient.withCustomOverrides = () => null;
service = new SomeService(customHttpClient);
});
describe('updateSomethingCool', () => {
it('calls put', () => {
spyOn(customHttpClient, 'put').and.stub();
service.updateSomethingCool(emptySignerVO);
expect(customHttpClient.put).toHaveBeenCalled();
});
});
现在很清楚,当我 运行 收到此失败消息时:
TypeError: Cannot read property 'put' of null
但是,我不知道如何在测试的 beforeEach
部分中定义 put
或 withCustomOverrides
方法。
请注意,CustomHttpClient
只是 Angular 的 HttpClient
的自定义包装器 class,允许一些更详细的功能。
感谢您的帮助!
我认为你应该注入 httpClient ;
beforeEach((http: HttpClient) => {
httpClient = http;
httpClient.put = () => null;
httpClient.withCustomOverrides = () => null;
service = new SomeService(log, httpClient);});
您是否使用 Angular 依赖注入将 HttpClient
注入 CustomHttpClient
?当测试依赖于 HttpClient
的服务时,您可以使用 HttpTestingController
,对于服务单元测试,这可能如下所示:
it(`should get a new data instance of type T`,
async(inject([TestDataService, HttpTestingController],
(service: TestDataService, backend: HttpTestingController) => {
// ... tests here
})
));
好吧,最后我实际上并没有那么远。实际测试代码没问题; beforeEach()
方法需要更新如下:
beforeEach(() => {
customHttpClient = <CustomHttpClient>{};
customHttpClient.put = () => null;
customHttpClient.withCustomOverrides = () => customHttpClient;
service = new SomeService(customHttpClient);
});
我基本上只需要将 customHttpClient
对象分配给 .withCustomOverides
方法。
如果您查看实际调用中方法链接的流程,这实际上是有道理的。
我有一种情况需要监视在调用另一个方法之后调用的方法。
这是正在测试的 class/method:
@Injectable()
export class SomeService {
constructor(private customHttpClient: CustomHttpClient) {
}
updateSomethingCool(signerVO: SignerVO): Observable<SignerVO> {
// ...
return this.customHttpClient.withCustomOverrides(new CustomErrorHandlerHttpInterceptorOverride({ passthroughStatusCodes: [BAD_REQUEST, BAD_GATEWAY] }))
.put<SignerVO>(`/my/url/goes/here`, signerVO);
}
}
此 class 使用 CustomHttpClient,如下所示:
@Injectable()
export class CustomHttpClient extends HttpClient {
private interceptors: HttpInterceptor[] | null = null;
constructor(private injector: Injector,
originalHandler: HttpHandler, private originalBackend: HttpBackend) {
super(originalHandler);
}
public withCustomOverrides(...overrides: CustomHttpInterceptorOverride[]): HttpClient {
// do very customizable things here
return new CustomDelegatingHttpClient(
new CustomHttpInterceptingHandler(this.originalBackend, this.interceptors, overrides));
}
}
export class CustomDelegatingHttpClient extends HttpClient {
constructor(private delegate: HttpHandler) {
super(delegate);
}
}
这是我的单元测试尝试,确实调用了 put
方法,因此我需要监视 put
方法:
describe(SomeService.name, () => {
let service: SomeService;
let customHttpClient: CustomHttpClient;
let emptySignerVO: SignerVO = new SignerVO();
beforeEach(() => {
customHttpClient= <CustomHttpClient>{};
customHttpClient.put = () => null;
customHttpClient.withCustomOverrides = () => null;
service = new SomeService(customHttpClient);
});
describe('updateSomethingCool', () => {
it('calls put', () => {
spyOn(customHttpClient, 'put').and.stub();
service.updateSomethingCool(emptySignerVO);
expect(customHttpClient.put).toHaveBeenCalled();
});
});
现在很清楚,当我 运行 收到此失败消息时:
TypeError: Cannot read property 'put' of null
但是,我不知道如何在测试的 beforeEach
部分中定义 put
或 withCustomOverrides
方法。
请注意,CustomHttpClient
只是 Angular 的 HttpClient
的自定义包装器 class,允许一些更详细的功能。
感谢您的帮助!
我认为你应该注入 httpClient ;
beforeEach((http: HttpClient) => {
httpClient = http;
httpClient.put = () => null;
httpClient.withCustomOverrides = () => null;
service = new SomeService(log, httpClient);});
您是否使用 Angular 依赖注入将 HttpClient
注入 CustomHttpClient
?当测试依赖于 HttpClient
的服务时,您可以使用 HttpTestingController
,对于服务单元测试,这可能如下所示:
it(`should get a new data instance of type T`,
async(inject([TestDataService, HttpTestingController],
(service: TestDataService, backend: HttpTestingController) => {
// ... tests here
})
));
好吧,最后我实际上并没有那么远。实际测试代码没问题; beforeEach()
方法需要更新如下:
beforeEach(() => {
customHttpClient = <CustomHttpClient>{};
customHttpClient.put = () => null;
customHttpClient.withCustomOverrides = () => customHttpClient;
service = new SomeService(customHttpClient);
});
我基本上只需要将 customHttpClient
对象分配给 .withCustomOverides
方法。
如果您查看实际调用中方法链接的流程,这实际上是有道理的。