2017-07-08 7 views
0

Ich teste eine sehr einfache Komponente, die die Login/Out-Schaltflächen anzeigt/versteckt.Angular2-Unit-Test, der keinen Mock-Service verwendet

Dafür spottete ich meine AuthService Service als AngularFire2.

Das Problem, das ich habe, ist, dass scheint, dass mein Schein-Service (Mock AuthService) nicht anstelle der tatsächlichen AuthService bereitgestellt wird.

Im Test should show the Facebook login button wird erwartet, dass service.isAnonymous nicht definiert ist. Im eigentlichen Dienst ist es. Aber im Scheindienst ist true. Dieser Test sollte fehlschlagen.

Beachten Sie auch, dass ich versuche, die Methode service.test(false); aufzurufen; Im Mock-Service existiert diese Methode und ist public. Aber ich erhalte den Fehler: Property 'Test' existiert nicht auf dem Typ 'AuthService'.

Dies deutet darauf hin, dass mein Scheindienst nicht zur Verfügung gestellt wird.

Sie können sehen, wie ich zwei Art und Weise versucht habe, den Mock-Service zur Verfügung zu stellen (ein Kommentar gesetzt ist) in meiner Test-Spezifikation:

import { DebugElement } from '@angular/core'; 
import { 
    async, 
    inject, 
    ComponentFixture, 
    TestBed 
} from '@angular/core/testing'; 
import { By } from '@angular/platform-browser'; 

import { FacebookLoginComponent } from './facebook-login.component'; 
import { AuthService } from '../shared/auth.service'; 
import { MockAuthService } from '../shared/testing/auth.service'; 

describe('FacebookLoginComponent',() => { 
    let authService: AuthService; 
    let component: FacebookLoginComponent; 
    let fixture: ComponentFixture<FacebookLoginComponent>; 
    let debugElement: DebugElement; 
    let htmlElement: HTMLElement; 

    beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     declarations: [ FacebookLoginComponent ], 
     // providers: [{ provide: AuthService, useValue: MockAuthService }] 
    }) 
     .compileComponents(); 

    TestBed.overrideComponent(FacebookLoginComponent, { 
     set: { 
     providers: [{ provide: AuthService, useClass: MockAuthService }] 
     } 
    }) 
    })); 

    beforeEach(() => { 
    fixture = TestBed.createComponent(FacebookLoginComponent); 
    component = fixture.componentInstance; 
    fixture.detectChanges(); 
    }); 

    it('should be created',() => { 
    expect(component).toBeTruthy(); 
    }); 

    it('should show the Facebook login button', inject([ AuthService ], (service: AuthService) => { 
    expect(service.isAnonymous).toBeUndefined(); 

    debugElement = fixture.debugElement.query(By.css('button')); 
    htmlElement = debugElement.nativeElement; 

    service.test(false); 

    expect(htmlElement.textContent).toBe('Facebook Login'); 
    })); 

    it('should show the Logout button',() => { 
    debugElement = fixture.debugElement.query(By.css('button')); 
    htmlElement = debugElement.nativeElement; 

    expect(htmlElement.textContent).toBe('Logout'); 
    }); 
}); 

Der Vollständigkeit; hier ist meine Mock-Service, MockAuthService:

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

@Injectable() 
export class MockAuthService { 
    public authState: { isAnonymous: boolean, uid: string }; 

    constructor() { 
    this.authState = { isAnonymous: true, uid: '0HjUd9owxPZ5kibvUCN6S2DgB4x1' }; 
    } 

    // public get currentUser(): firebase.User { 
    // return this.authState ? this.authState : undefined; 
    // } 

    // public get currentUserObservable(): Observable<firebase.User> { 
    // return this.afAuth.authState; 
    // } 

    public get currentUid(): string { 
    return this.authState ? this.authState.uid : undefined; 
    } 

    public get isAnonymous(): boolean { 
    return this.authState ? this.authState.isAnonymous : false; 
    } 

    public get isAuthenticated(): boolean { 
    return !!this.authState; 
    } 

    // public logout(): void { 
    // this.afAuth.auth.signOut(); 
    // } 

    public test(isAnonymous: boolean) { 
    this.authState.isAnonymous = isAnonymous; 
    } 
} 

ich ratlos bin, wie stattdessen die mock zu liefern.

Update:

Basierend auf Antworten und Kommentare Bis jetzt habe ich meine Mock Test spec aktualisieren. Ich habe jedoch immer noch das gleiche Problem.

Ich bekomme den Fehler Eigenschaft 'Test' existiert nicht auf den Typ 'AuthService'.

Dies deutet darauf hin, es ist immer noch nicht ersetzen den Schein für die tatsächliche authService Service.

Außerdem, wenn ich hinzufügen:

public test(test: boolean): boolean { 
    return test; 
} 

Zum eigentlichen Dienst der Test fehlschlägt; aber nicht wegen des oben genannten Fehlers, sondern weil es die Erwartungen des Tests nicht erfüllen sollte.

Das ist meine aktualisierte Spezifikation:

import { DebugElement } from '@angular/core'; 
import { 
    async, 
    inject, 
    ComponentFixture, 
    TestBed 
} from '@angular/core/testing'; 
import { By } from '@angular/platform-browser'; 

import { FacebookLoginComponent } from './facebook-login.component'; 
import { AuthService } from '../shared/auth.service'; 
import { MockAuthService } from '../shared/testing/auth.service'; 

describe('FacebookLoginComponent',() => { 
    let authService: AuthService; 
    let component: FacebookLoginComponent; 
    let fixture: ComponentFixture<FacebookLoginComponent>; 
    let debugElement: DebugElement; 
    let htmlElement: HTMLElement; 

    beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     declarations: [ FacebookLoginComponent ], 
     providers: [{ provide: AuthService, useClass: MockAuthService }] 
    }).compileComponents(); 
    })); 

    beforeEach(() => { 
    fixture = TestBed.createComponent(FacebookLoginComponent); 
    component = fixture.componentInstance; 
    fixture.detectChanges(); 
    }); 

    it('should be created',() => { 
    expect(component).toBeTruthy(); 
    }); 

    it('should show the Facebook Login button', inject([ AuthService ], (service: AuthService) => { 
    debugElement = fixture.debugElement.query(By.css('button')); 
    htmlElement = debugElement.nativeElement; 

    expect(htmlElement.textContent).toBe('Facebook Login'); 
    })); 

    it('should show the Logout button', inject([ AuthService ], (service: AuthService) => { 
    expect(service.isAnonymous).toBe(true); 

    debugElement = fixture.debugElement.query(By.css('button')); 
    htmlElement = debugElement.nativeElement; 

    service.test(false); 

    fixture.detectChanges(); 

    expect(htmlElement.textContent).toBe('Logout'); 
    })); 
}); 
+0

Es ist eine Klasse, kein Wert; 'useClass: MockAuthService' oder' useValue: new MockAuthService() '. – jonrsharpe

+0

Danke @jonrsharpe, ich habe meine Testspezifikation aktualisiert, obwohl ich immer noch dieses Problem habe. Bitte sehen Sie meine aktualisierte Frage. –

+0

Was passiert, wenn Sie auf '(service as MockAuthService) .test' zugreifen? – jonrsharpe

Antwort

1
beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     declarations: [ FacebookLoginComponent ], 
     // providers: [{ provide: AuthService, useValue: MockAuthService }] 
    }) 
     .compileComponents(); 

    TestBed.overrideComponent(FacebookLoginComponent, { 
     set: { 
     providers: [{ provide: AuthService, useClass: MockAuthService }] 
     } 
    }) 
    })); 

Es gibt zwei Probleme. Sie müssen die Provider der Komponenten nicht überschreiben, da Sie diese bei der Konfiguration der TestBed angeben können.

Ich nehme an, dass Sie die Komponente überschrieben haben, weil die ursprüngliche Konfiguration nicht funktionierte. Es hat nicht funktioniert, weil Sie useValue anstelle von useClass verwendet haben.

// providers: [{ provide: AuthService, useValue: MockAuthService }] 

sollte dies tun:

beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     declarations: [ FacebookLoginComponent ], 
     providers: [{ provide: AuthService, useClass: MockAuthService }] 
    }).compileComponents(); 
    })); 

EDIT:

Wenn inject Funktion verwenden, sollten Sie MockAuthService als Typ verwenden. TypeScript sollte aufhören sich zu beschweren.

inject([ AuthService ], (service: MockAuthService) => { /* ... */ }); 
+0

Vielen Dank für Ihren Vorschlag, aber leider scheint dies immer noch den ursprünglichen (nicht den Schein) Dienst zu verwenden, siehe meine aktualisierte Frage. –

+0

Ich habe meine Antwort aktualisiert. –

+1

Ich könnte mich selbst treten, danke! –

Verwandte Themen