I'm having a directive (but it should be the same for a component or service) which injects an abstract class. To be accurate, the base class is used as the token and I have to provide the concrete class manually somewhere.
It means I'm providing my concrete class as follows:
beforeEach(() => {
return MockBuilder(MyDirective).provide({
provide: MyAbstractClass,
useClass: MyConcreteClass,
});
});
But, I would also like to spy the provided class. Using jasmine, I added ngMock's helper ngMocks.autoSpy('jasmine')
. However, the injected concrete service is not auto spied.
This is because providing it through the useClass property will bypass any ngMock logic to inject it's own spied injectables.
The workaround is to manually add the spy using spyOn(MyConcreteClass, 'aPropertyName').and.callThrough();
to then check if the class toHaveBeenCalled()
. But this is cumbersome.
I therefore refactored my MockBuilder as follows:
beforeEach(() => {
return MockBuilder(MyDirective, [
MyConcreteClass,
]).provide({
provide: MyAbstractClass,
useExisting: MyConcreteClass,
});
});
And then only, the class MyConcreteClass is autoSpied. However, It is a mocked, i.e. without any implementation.
How can I then provide a service, spy it keeping all its implementation ?