在Ionic2(Angular2)项目的Jasmine测试中对Navock的Mock进行间谍故障

时间:2017-05-16 11:53:18

标签: angular unit-testing jasmine mocking ionic2

我已根据Josh Morony's TDD tutorial创建了一个Ionic2项目。我使用的是左侧菜单(在应用模块中定义),因此我尝试在菜单中的链接上编写测试。

不幸的是,我收到的错误是我无法弄清楚的。它似乎与NavController有关,所以也许我需要改变我嘲笑它的方式。我应该使用mockNavController from the Ionic library吗?来自mockNavController的{​​{1}}似乎没有帮助......

错误由../../node_modules/ionic-angular/util/mock-providers触发。我在下面的块中删除了一些代码,但我认为我包含了与错误相关的所有内容。

app.component.spec.ts

fixture.detectChanges()

mocks.ts

import { async, TestBed } from '@angular/core/testing';
import { By }           from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { IonicModule, Platform, NavController } from 'ionic-angular';
import { NavMock, StatusBarMock, SplashScreenMock } from '../mocks';

import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { MyApp } from './app.component';
import { PlatformMock } from '../../test-config/mocks-ionic';
import { HomePage } from '../pages/home/home';

describe('MyApp Component', () => {
  let fixture;
  let component;
  let de: DebugElement;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        MyApp,
        HomePage
      ],
      imports: [
        IonicModule.forRoot(MyApp)
      ],
      providers: [
        { provide: NavController, useClass: NavMock },
        { provide: StatusBar, useClass: StatusBarMock },
        { provide: SplashScreen, useClass: SplashScreenMock },
        { provide: Platform, useClass: PlatformMock },
        OverlayService
      ]
    })
  }));

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

  it ('should be created', () => {
    expect(component instanceof MyApp).toBe(true);
  });

  it('displays the home page to the user', () => {
    expect(component['rootPage']).toBe(HomePage);
  });

  it('links to the pages in the menu', () => {
    let navCtrl = fixture.debugElement.injector.get(NavController);
    spyOn(navCtrl, 'setRoot');

    fixture.detectChanges();
    de = fixture.debugElement.query(By.css('#menu-content ion-list button'));

    de[0].triggerEventHandler('click', null);
    expect(navCtrl.setRoot).toHaveBeenCalledWith(HomePage, {});
  });

});

app.component.ts

export class NavMock {

  public pop(): any {
    return new Promise(function(resolve: Function): void {
      resolve();
    });
  }

  public push(): any {
    return new Promise(function(resolve: Function): void {
      resolve();
    });
  }

  public getActive(): any {
    return {
      'instance': {
        'model': 'something',
      },
    };
  }

  public setRoot(): any {
    return true;
  }

  // ADDED TO PUSH FORWARD THIS TEST PAST A PREVIOUS ERROR
  public registerChildNav(): any {
    return true;
  }

  // ADDED TO TRY AND FIX THIS ERROR
  public _config: any = {
    plt: {
      isRTL: function() {return true;}
    }
  }
}

export class PlatformMock {
  public ready(): any {
    return new Promise((resolve: Function) => {
      resolve();
    });
  }
}

export class StatusBarMock {
  public styleDefault(): any {
    return true;
  }
}

export class SplashScreenMock {
  public hide(): any {
    return true;
  }
}

app.html

import { Component, ViewChild } from '@angular/core';
import { Nav, Platform } from 'ionic-angular';
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';

import { HomePage } from '../pages/home/home';


@Component({
  templateUrl: 'app.html',
  entryComponents: [
    HomePage
  ]
})
export class MyApp {
  @ViewChild(Nav) nav: Nav;

  rootPage: any = HomePage;

  pages: Array<{title: string, component: any}>;

  constructor(public platform: Platform, public statusBar: StatusBar, public splashScreen: SplashScreen) {
    this.initializeApp();

    // used for an example of ngFor and navigation
    this.pages = [
      { title: 'Home', component: HomePage }
    ];

  }

  initializeApp() {
    this.platform.ready().then(() => {
      // Okay, so the platform is ready and our plugins are available.
      // Here you can do any higher level native things you might need.
      this.statusBar.styleDefault();
      this.splashScreen.hide();
    });
  }

  openPage(page) {
    // Reset the content nav to have just this page
    // we wouldn't want the back button to show in this scenario
    this.nav.setRoot(page.component);
  }
}

测试控制台中显示的错误:

<ion-menu [content]="content">
  <ion-header>
    <ion-toolbar color="dark">
      <ion-title>MyApp</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-content id="menu-content">
    <ion-list>
      <button menuClose ion-item *ngFor="let p of pages" (click)="openPage(p)">
        {{p.title}}
      </button>
    </ion-list>
  </ion-content>

</ion-menu>

<ion-nav [root]="rootPage" #content swipeBackEnabled="false"></ion-nav>

0 个答案:

没有答案