I have a service with a property and a getter. The property is set in the service constructor like this:
public readonly usersMetaData: Observable<User | null>;
constructor(private afAuth: AngularFireAuth,
private afs: AngularFirestore) {
this.usersMetaData = this.afAuth.authState.pipe(switchMap((user: firebase.User) => {
if (user) {
return this.afs.doc<User>(`users/${user.uid}`).valueChanges();
} else {
return of(null);
}
}), share());
}
My getter just tests if the authstate returns a defined object basically (not null, not undefined):
public isAuthenticated(): Observable<boolean> {
return this.usersMetaData.pipe(map(user => !!user));
}
Now for my unit test setup, I need to mock authState from firebase. It looks as follows:
let service: AuthService;
const authStub: any = {
authState: {}
};
const storeStub = {
doc() {
return of(null);
}
};
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
{provide: AngularFireAuth, useValue: authStub},
{provide: AngularFirestore, useValue: storeStub},
AuthService
]
});
authStub.authState = of({username: 'test'});
spyOn(storeStub, 'doc').and.stub();
service = TestBed.get(AuthService);
});
it('should check for authentication - is authenticated', async(() => {
service.isAuthenticated().subscribe(isUser => console.log(isUser)); <== should return true
}));
The error that is returning is: Failed: Cannot read property 'valueChanges' of undefined
Does anyone know how to mock authstate properly?
Almost right. The storeStub obj needs to be modified like this:
const storeStub = {
doc() {
return {
valueChanges() {
return of({property: 'test'});
}
};
}
};
since doc calls valueChanges you need to return valueChanges in your mocked object.