I have a situation where I need to spy on a method that is called after another method is called.
Here's the class/method under test:
@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);
}
}
This class uses CustomHttpClient which looks like this:
@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);
}
}
Here's my attempt at unit testing that the put
method has indeed been called, hence I need to spy on the put
method:
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();
});
});
Now clearly when I run this I receive this failure message:
TypeError: Cannot read property 'put' of null
However, I do not know exactly how to define either the put
or withCustomOverrides
methods in the beforeEach
portion of the test.
Note that CustomHttpClient
is simply a customized wrapper class around Angular's HttpClient
that allows some more detailed functionality.
Thank you for your help!
Well, in the end I wasn't that far off actually. The actual test code was fine; the beforeEach()
method needs updated as follows:
beforeEach(() => {
customHttpClient = <CustomHttpClient>{};
customHttpClient.put = () => null;
customHttpClient.withCustomOverrides = () => customHttpClient;
service = new SomeService(customHttpClient);
});
I basically just had to assign the customHttpClient
object to the .withCustomOverides
method.
Which, if you look at the flow of the method chaining in the real call, actually makes sense.