angularunit-testingrxjsjasmineangularfire

Angular Unit Testing - Observable without Subscribing


In my auth service, I'm calling a function from angularFireAuth called onAuthStateChanged. The documentation describes this as nextOrObserver with a 'callback triggered on change'. I understand that when a user logs in or out, onAuthStateChanged will emit either a firebase.User object or null.

The problem is that from a unit testing perspective, I'm not actually returning an observable so I can't subscribe to it and make my assertions inside the subscription.

I am able to spy on 'onAuthStateChanged', but that's as far as my tests get in the code. I'm not sure how I'm supposed to correctly emit or mock the observable response from onAuthStateChanged so that I can test the logic branches.

function to unit test

  initialize(){

    this.afAuth.onAuthStateChanged((user: User | null) => {
      if (user) {
        
        this.userData = {
          uid: user.uid,
          email: user.email,
          emailVerified: user.emailVerified
        };
        this.liveUid = user.uid

        if (typeof window !== 'undefined' && window.localStorage) {
          localStorage.setItem('user', JSON.stringify(this.userData));
        }

      }
      else {
        this.userData = null

        if (typeof window !== 'undefined' && window.localStorage) {
          localStorage.setItem('user', 'null');
        }

      }
    })
  }

my mock for angularFire

export const AngularFireAuthMock: any = {

const authState: User = {
    uid: 'fakeuser',
    email: 'test@test.com',
    emailVerified: true
};

    onAuthStateChanged: () => { 
        return of(authState)
    },
}

spect.ts

  it('userData populated Successfully', fakeAsync(() => {

     const spy = spyOn(AngularFireAuthMock, 'onAuthStateChanged').and.callThrough()

     service.initialize()
   
     expect(spy).toHaveBeenCalled()
     console.log(service.userData)

  }));

Solution

  • I guess you just need to trigger callback so that your mocked method should be like:

    onAuthStateChanged: (callbackFn: (value: any) => void) => { 
      callbackFn(authState)
    },