2017-07-08 89 views
0

我正在測試一個顯示/隱藏登錄/退出按鈕的非常簡單的組件。Angular2單元測試不使用模擬服務

爲此我嘲笑我的AuthService服務,因爲它依賴於AngularFire2。

我遇到的問題是出現我的模擬服務(Mock AuthService)沒有被提供來代替實際的AuthService

在測試should show the Facebook login button,service.isAnonymous預計未定義。在實際的服務中,它是。但在模擬服務是true。這個測試應該失敗。

另外,請注意我正在嘗試調用方法service.test(false);;在模擬服務中,此方法存在並且是public。但是我收到錯誤:類型'AuthService'上不存在屬性「測試」。

這表明我的模擬服務沒有提供。

你可以看到我是如何嘗試了兩種方式,在我的測試規範提供模擬服務(一個被註釋掉):

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

爲了完整;這裏是我的模擬服務,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; 
    } 
} 

我不知道如何提供模擬代替。

更新:根據答案和評論到目前爲止我有更新我的模擬測試規範

。但是,我仍然有同樣的問題。

我得到錯誤類型'AuthService'上不存在屬性'test'。

這表明它仍然沒有用實際的authService服務替代模擬。

而且,當我添加:

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

給實際的服務測試失敗;但不是因爲上面的錯誤,而是因爲它應該 - 測試的期望沒有得到滿足。

這是我的最新規範:

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

這是一個類,而不是一個值; 'useClass:MockAuthService'或'useValue:new MockAuthService()'。 – jonrsharpe

+0

謝謝@jonrsharpe,儘管我仍然遇到這個問題,但我已經更新了測試規範。請看我更新的問題。 –

+0

如果你訪問'(service作爲MockAuthService).test'會怎麼樣? – jonrsharpe

回答

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

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

有兩個問題。 您不需要覆蓋組件的提供者,因爲您可以在配置TestBed時提供它們。

我認爲你已經開始覆蓋組件,因爲初始配置不起作用。它不起作用,因爲您使用useValue而不是useClass

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

這應該這樣做:

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

編輯:

使用inject功能,你應該使用MockAuthService作爲一種類型。 TypeScript應該停止抱怨。

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

感謝您的建議,但不幸的是,這似乎仍然使用原始(不是模擬)服務,請參閱我的更新問題。 –

+0

我已經更新了我的答案。 –

+1

我可以踢自己,謝謝! –

相關問題