I have a core service that gets an instance of the firebase.auth
obj and returns it with a getter. It is simple and looks as follows:
export class AuthService {
...
constructor(private afAuth: AngularFireAuth,
private afs: AngularFirestore) {
...
}
public getAuthInstance(): FirebaseAuth {
return this.afAuth.auth;
}
}
Now I have a LoginService that needs the AuthService for logging into my app.
export class LoginService {
constructor(private authService: AuthService) {
}
public login(email, password): Promise<UserCredential | string> {
return this.authService.getAuthInstance().signInWithEmailAndPassword(email, password)
.catch(() => Promise.reject('Login failed.'));
}
Also not too complex. But now I want to test my login comp. - specifically the login
method. I am not able to mock signInWithEmailAndPassword
. I tried basically everything:
jasmine.spies
The test class looks as follows:
...
const authStub: AuthService = jasmine.createSpyObj('AuthService', ['getAuthInstance']);
const fireStub = {
auth: {
signInWithEmailAndPassword() {
return Promise.resolve();
}
}
};
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{provide: AuthService, useValue: authStub},
{provide: AngularFireAuth, useValue: fireStub},
LoginService
]
});
});
const spy = it('should call signInWithPasswordAndEmail', inject([LoginService], (service: LoginService) => {
(<jasmine.Spy>authStub.getAuthInstance).and.returnValue({username: 'test'});
spyOn(fireStub.auth, 'signInWithEmailAndPassword').and.callThrough();
service.login(email, password).then(() => expect(spy).toHaveBeenCalledTimes(1));
}));
Can anyone help me to get this damn test green? xD^^ The Error msg. That ist thrown is: this.getAuthInstance().signInWithEmail.... Is Not a function
After some Trial and Error I mocked the AuthService
indirectly with AngularFireAuth
and AngularFireStore
the test configuration looks as follows:
describe('LoginService', () => {
const email: string = 'email';
const password: string = 'password';
const authStub: any = {
authState: {},
auth: {
signInWithEmailAndPassword() {
return Promise.resolve();
}
}
};
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{provide: AngularFireAuth, useValue: authStub},
{provide: AngularFirestore},
LoginService
]
});
authStub.authState = of(null);
});
it('should call signInWithPasswordAndEmail', inject([LoginService], (service: LoginService) => {
const mock = TestBed.get(AngularFireAuth);
const spy = spyOn(authStub.auth, 'signInWithEmailAndPassword').and.callThrough();
mock.auth = authStub.auth;
service.login(email, password);
expect(spy).toHaveBeenCalledWith(email, password);
}));
});
It gets the job done. If someone has a better solution, I would be pleased to know.