I have defined an interface and opaque token as follows
export let AUTH_SERVICE = new OpaqueToken('auth.service');
export interface AuthService {
logIn(): void;
logOut(): void;
}
In my test class I provide a stubbed version of AuthService
, i.e.,
@Injectable()
class AuthServiceStub implements AuthService {
logIn(): void {}
logOut(): void {}
}
and set up my test beforeEach
as follows
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ LoginComponent ],
providers: [
{provide: AUTH_SERVICE, useValue: AuthServiceStub}
]
});
}));
I then started to write the test, i.e.,
it('should call log in on AuthService', () => {
let authService = fixture.debugElement.injector.get(AUTH_SERVICE);
spyOn(authService, 'logIn');
// expect will go here
});
but I get the following error
Error: <spyOn> : logIn() method does not exist
Can't see what I'm doing wrong. Any ideas?
That's because you're using useValue
property in the provider object. That means the injected value will be the AuthServiceStub
class itself. What you want instead, is its instance that actually have those methods.
To make the test works, replace useValue
with useClass
. This will make the Angular's dependency injection system to actually instantiate the service when the provider is created and your call fixture.debugElement.injector.get(AUTH_SERVICE);
will return a proper object.
Alternatively you could instantiate the class manually:
it('should call log in on AuthService', () => {
let AuthService = fixture.debugElement.injector.get(AUTH_SERVICE);
let authService = new AuthService();
spyOn(authService, 'logIn');
// expect will go here
});
Still, useClass
is a better solution, since it will handle all future injections that the AuthService
might need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With