离子茉莉花测试模拟提供者

时间:2017-09-07 08:14:41

标签: angular ionic2 jasmine

我正在为登录页面创建单元测试(离子3角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()

  }

}

我在单元测试中尝试实现的是测试提供者的登录方法是否被调用。

我的单元测试如下:

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()
    })

});

我无法理解的是调用了我的mock类的login方法。我在控制台中有警告消息(WARN LOG:&#39; MOCK TEST&#39;)。

但我的测试 A Test 失败并显示消息:

Expected spy test to have been called.

1 个答案:

答案 0 :(得分:3)

控制台中的

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()