Angular firebase - 使用 angularFireAuth 对服务进行单元测试

Angular firebase - Unit testing a service using angularFireAuth

我有一个核心服务,它获取 firebase.auth obj 的实例并 returns 它带有 getter。它很简单,如下所示:

export class AuthService {

  ...
  constructor(private afAuth: AngularFireAuth,
              private afs: AngularFirestore) {
  ...
}

  public getAuthInstance(): FirebaseAuth {
    return this.afAuth.auth;
  }
}

现在我有一个 LoginService 需要 AuthService 来登录我的应用程序。

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.'));
  }

也不算太复杂。但现在我想测试我的登录组件。 - 特别是 login 方法。我无法模拟 signInWithEmailAndPassword。我基本上尝试了一切:

测试 class 如下所示:

  ...
  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));
  }));

谁能帮我把这个该死的测试改成绿色? xD^^ 错误消息。抛出的是:this.getAuthInstance().signInWithEmail.... 不是函数

经过反复试验,我用 AngularFireAuthAngularFireStore 间接模拟了 AuthService,测试配置如下所示:

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);
  }));
});

它完成了工作。如果有人有更好的解决方案,我很乐意知道。