2017-09-16 4 views
0

In meiner Angular2 App, die AngularFire2 verwendet, habe ich eine AuthService die versucht, anonym mit Firebase zu authentifizieren.Test für abgelehnte Versprechen mit Jasmine

Ich versuche, einen Test zu schreiben, der AngularFireAuth 's signInAnonymously erwartet, um eine abgelehnte Zusage zurückzugeben; für authState zu null und ein Fehler geworfen werden.

Ich bin ein neuer Jasmine und Test im Allgemeinen, aber ich denke, ich muss möglicherweise asynchrone Tests verwenden, aber ich bin ziemlich stecken.

Hier ist eine vereinfachte AuthService:

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: firebase.User) => { 
     if (authState === null) { 
     this.afAuth.auth.signInAnonymously() 
      .then((authState) => { 
      this.authState = authState; 
      }) 
      .catch((error) => { 
      throw new Error(error.message); 
      }); 
     } else { 
     this.authState = authState; 
     } 
    }, (error) => { 
     throw new Error(error.message); 
    }); 
    } 
} 

Und hier meine Testspezifikt sind:

import { TestBed, inject } 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 { environment } from '../environments/environment'; 

describe('AuthService',() => { 
    const mockAngularFireAuth: any = { 
    auth: jasmine.createSpyObj('auth', { 
     'signInAnonymously': Promise.resolve('foo'), 
     // 'signInWithPopup': Promise.reject(), 
     // 'signOut': Promise.reject() 
    }), 
    authState: Observable.of(null) 
    }; 

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

    it('should be created', inject([ AuthService ], (service: AuthService) => { 
    expect(service).toBeTruthy(); 
    })); 

    // 
    // 
    // 
    // 
    // 

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

    it('should thow', inject([ AuthService ], (service: AuthService) => { 
     expect(mockAngularFireAuth.auth.signInAnonymously).toThrow(); 
    })); 
    }); 

    // 
    // 
    // 
    // 
    // 

}); 

Vielen Dank für Ihre Hilfe!

+0

Warum schreiben Sie den Test für der Schein? Was soll der zu testende Code tun? – jonrsharpe

+0

Hallo @jonrsharpe, ich verspotte 'AngularFireAuth's' signInAnonymous ', sonst würde es jedes Mal, wenn die Tests ausgeführt werden, tatsächlich Firebase aufrufen. Ich werde dazu gebracht zu glauben, dass ich diese Art von Drittanbieter verspotten soll? –

+0

Ja, aber dieser Schein ist das einzige, was dein Test zu trainieren scheint. – jonrsharpe

Antwort

0

Es stellt sich heraus, dass ich mockAngularFireAuth richtig verspottete. Ich brauchte mockAngularFireAuth.auth signInAnonymously() ‚s Versprechen mit einem Fehler zu verwerfen und erwarten, dass sie gefangen werden, a la:

import { TestBed, async, inject } 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 './mock-user'; 
import { environment } from '../environments/environment'; 

describe('AuthService',() => { 
    // An anonymous user 
    const authState: MockUser = { 
    displayName: null, 
    isAnonymous: true, 
    uid: '17WvU2Vj58SnTz8v7EqyYYb0WRc2' 
    }; 

    const mockAngularFireAuth: any = { 
    auth: jasmine.createSpyObj('auth', { 
     'signInAnonymously': Promise.reject({ 
     code: 'auth/operation-not-allowed' 
     }), 
     // 'signInWithPopup': Promise.reject(), 
     // 'signOut': Promise.reject() 
    }), 
    authState: Observable.of(authState) 
    }; 

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

    it('should be created', inject([ AuthService ], (service: AuthService) => { 
    expect(service).toBeTruthy(); 
    })); 

    describe('can authenticate anonymously',() => { 
    describe('AngularFireAuth.auth.signInAnonymously()',() => { 
     it('should return a resolved promise',() => { 
     mockAngularFireAuth.auth.signInAnonymously() 
      .then((data: MockUser) => { 
      expect(data).toEqual(authState); 
      }); 
     }); 
    }); 
    }); 

    describe('can’t authenticate anonymously',() => { 
    describe('AngularFireAuth.auth.signInAnonymously()',() => { 
     it('should return a rejected promise',() => { 
     mockAngularFireAuth.auth.signInAnonymously() 
      .catch((error: { code: string }) => { 
      expect(error.code).toEqual('auth/operation-not-allowed'); 
      }); 
     }); 
    }); 
    }); 
    … 
}); 
+0

Wenn Sie erwarten, dass das Versprechen abgelehnt wird, verpassen Sie einen Check, wenn das Versprechen erfüllt wurde. Und auch umgekehrt. –

0

Ich löste dieses Problem, indem Sie folgendermaßen vorgehen:

describe('should reject promise',() => { 

     let resolved: boolean; 
     let rejected: boolean; 
     let _e: any; 

     beforeEach(function (done) { 
      resolved = false; 
      rejected = false; 
      // ensure conditions here are such that myFn() should return a rejected promise 
      service.myFn().then(() => { 
       resolved = true; 
       done(); 
      }).catch((e) => { 
       rejected = true; 
       _e = e; 
       done(); 
      }); 
     }) 

     it('should reject',() => { 
      expect(resolved).toEqual(false); 
      expect(rejected).toEqual(true); 
      expect(_e.name).toEqual("MyCustomErrorName"); 
     }); 
    }); 
Verwandte Themen