单元测试模拟拒绝了 Angular2 中的承诺

Unit Test Mock Rejected Promise in Angular2

我正在尝试测试 Angular2 身份验证服务 (authService),特别是模拟 AngularFireAuth 提供程序,以便我可以通过监视和返回值来控制和测试各种身份验证场景AngularFireAuth 方法,例如signInAnonymously.

以下是我的测试规范的摘录。你可以看到初始的 authState 是一个 null 的 Observable——我们没有通过身份验证。 authService 然后应该尝试匿名验证(使用 signInAnonymously)。

AngularFire signInAnonymously 方法中 returns 一个承诺。我希望它被拒绝并捕获错误。

这只是一次场景,但如果我能解决这个问题,我可能就能解决剩下的问题。

auth.service.spec.ts

import { inject, TestBed } from '@angular/core/testing';

import { AngularFireAuth } from 'angularfire2/auth';
import 'rxjs/add/observable/of';
import { Observable } from 'rxjs/Rx';

import { AuthService } from './auth.service';
import { MockUser } from './testing/mock-user';
import { environment } from '../../environments/environment';

let authState: MockUser;
let mockAngularFireAuth: any = {
  auth: jasmine.createSpyObj('auth', [
    'signInAnonymously',
    'signInWithPopup',
    'signOut'
  ]),
  authState: Observable.of(null)
};
let service: AuthService;

fdescribe('AuthService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        { provide: AngularFireAuth, useValue: mockAngularFireAuth },
        { provide: AuthService, useClass: AuthService }
      ]
    });
  });

  beforeEach(inject([ AuthService ], (authService: AuthService) => {
    service = authService;
  }));

  // TODO: Test `authState`  is `null` and throw
  describe('when we can’t authenticate', () => {
    it('should thow', () => {
      mockAngularFireAuth.auth.signInAnonymously.and.returnValue(() => {
        return new Promise((resolve, reject) => {
          reject('fooBar');
        });
      });
    });
  });
});

auth.service.ts

import { Injectable } from '@angular/core';

import { AngularFireAuth } from 'angularfire2/auth';
import * as firebase from 'firebase/app';
import { Observable } from 'rxjs/Rx';

@Injectable()
export class AuthService {
  private authState: firebase.User;

  constructor(private afAuth: AngularFireAuth) { this.init(); }

  private init(): void {
    this.afAuth.authState.subscribe((authState) => {
      console.log(1, authState);

      if (authState === null) {
        console.log(2, authState);

        this.afAuth.auth.signInAnonymously()
          .then((authState) => {
            console.log(3, authState);

            this.authState = authState;
          })
          .catch((error) => {
            console.log(4, error.message);

            throw new Error(error.message);
          });
      } else {
        console.log(5, authState);

        this.authState = authState;
      }
    }, (error) => {
      console.log(6, error.message);

      throw new Error(error.message);
    });
  }
}

我得到的错误是 Cannot read property 'then' of undefinedauth.service.ts 的第 21:11 行;正如您所期望的那样,.then((authState) => {... 行。

AuthService 在模拟 signInAnonymously.

之前实例化

相反,它可以是

  describe('when we can’t authenticate', () => {
    beforeEach(() => {
      mockAngularFireAuth.auth.signInAnonymously.and.returnValue(Promise.reject('fooBar'));
    });

    it('...', inject([ AuthService ], (authService: AuthService) => {
      ...