2017-09-07 21 views
1

私はログインページ(ionic 3 angular 4 j)の単体テストを作成しています。アプリケーションが構築されていますionic unit test exampleイオンジャスミンテスト模擬プロバイダ

私は自分のユーザーを認証しているプロバイダーを模擬しようとしています。

class UsersProviderMock { 
    public login():any { 
     console.warn("MOCK TEST") 
    } 
} 

マイログインページのコードは次のとおりです。私は私のユニットテストで達成しようとしています何

import { Component } from '@angular/core'; 
import { IonicPage, NavController, NavParams } from 'ionic-angular'; 
import { DashboardPage } from '../dashboard/dashboard' 
import { Platform } from 'ionic-angular'; 
import {UsersProvider} from '../../providers/users/users' 

@IonicPage() 
@Component({ 
    selector: 'page-login', 
    templateUrl: 'login.html', 
    providers:[UsersProvider] 
}) 
export class LoginPage { 

    email: string = ""; 
    password: string = ""; 

    constructor(public navCtrl: NavController, 
    public navParams: NavParams, 
    private platform: Platform, 
    private userprovider:UsersProvider) { } 

    ionViewDidLoad() { 
    } 

    login() { 

    console.warn("LOGIN")  
    this.userprovider.login() 

    } 

} 

は、プロバイダのloginメソッドが呼び出されることをテストすることです。私のモッククラスのloginメソッドが呼び出されるということです私は理解できない何

describe('Login',() => { 
    let inputs: DebugElement[]; 
    let comp: LoginPage; 
    let fixture: ComponentFixture<LoginPage>; 
    var mock; 

    beforeEach(async(() => { 

     TestBed.configureTestingModule({ 
     declarations: [LoginPage], 
     imports: [ 
      HttpModule, 
      IonicModule.forRoot(LoginPage) 
     ], 
     providers: [ 
      UsersProvider, 
      { provide: Apollo, useClass: ApolloMock }, 
      NavController, 
      { provide: ToastController, useClass:() => ToastControllerMock.instance() }, 
      { provide: LoadingController, useClass:() => LoadingControllerMock.instance() }, 
      { provide: NavParams, useClass: NavParamsMock }, 
      { provide: Platform, useClass: PlatformMock }, 
      { provide: StatusBar, useClass: StatusBarMock }, 
      { provide: SplashScreen, useClass: SplashScreenMock }, 
     ] 
     }).overrideComponent(LoginPage, { 
     set: { 
      providers: [ 
       { provide: UsersProvider, useClass: UsersProviderMock } 
      ] 
     } 
    }) 



     fixture = TestBed.createComponent(LoginPage); 
     mock=TestBed.get(UsersProvider) 
     comp = fixture.componentInstance; 
    })) 

    it('A Test',()=>{ 
     spyOn(mock,'login') 
     comp.login() 
     expect(mock.login).toHaveBeenCalled() 
    }) 

}); 

私のユニットテストは次のようになります。コンソールに警告メッセージがあります(WARN LOG: 'MOCK TEST')。

しかし、私のテストテストはメッセージで失敗します。コンソールで

Expected spy test to have been called. 

答えて

2

MOCK TESTはスパイが呼び出されなかった、元UsersProviderMockメソッドが代わりに呼び出されたことを意味します。 - あるコンポーネントは、独自のインジェクタからインスタンスを取得しながら

class UsersProviderMock { 
    public login():any { 
     throw new Error('should not be called'); 
    } 
} 

mock=TestBed.get(UsersProvider)は、ルートインジェクタからプロバイダインスタンスを取得します。障害のある行動を検出するためのより良い方法が呼び出されることになっていない方法でエラーをスローすることです無限UsersProviderMockmockは、テスト自体ではなくどこでも使用されていないプロバイダインスタンスです。 UsersProviderが床をテストするために設けられたので、それは必要ありませんが、このシナリオでは、可能である:コンポーネントインスタンスをスパイする

providers: [ 
     UsersProvider, 
     ... 

一つの方法(this answerで説明したように)プロトタイプ法をスパイすることである。

spyOn(UsersProviderMock.prototype,'login') 
    comp.login() 
    expect(UsersProviderMock.prototype.login).toHaveBeenCalled() 

それはここに冗長だからもう一つの方法は全くUsersProviderMockクラスを避けるためです:

set: { 
     providers: [ 
      { provide: UsersProvider, useValue: jasmine.createSpyObj('users', ['login']) } 
     ] 
    } 

    ... 
    comp.login() 
    expect(UsersProviderMock.prototype.login).toHaveBeenCalled() 
+0

は、この明確な説明のためにありがとうございました。 – gpasse