Karma TestBed.configureTestingModule:单元测试通过,但引发错误:"未处理的承诺拒绝:",'invalid link: LoginPage'



我有一个离子应用程序,我尝试在其中添加单元测试,测试通过了,但我总是有一个无法解决的错误。

但是,我的模块似乎定义和导入得很好。

这是我正在测试的文件:

app.component.ts

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 {BackendClient} from "../backend/client.service";
@Component({
templateUrl: 'app.html',
providers: [BackendClient]
})
/**
* Main class of Alignak App Mobile
*/
export class MyApp {
@ViewChild(Nav) nav: Nav;
rootPage:any = 'LoginPage';
/**
* @param {Platform} platform - platform Object
* @param {StatusBar} statusBar - status bar Object
* @param {SplashScreen} splashScreen - splash screen Object
* @param {BackendClient} backend - backend client
*/
constructor(public platform: Platform, public statusBar: StatusBar,
public splashScreen: SplashScreen, public backend: BackendClient) {
this.initializeApp()
}
/**
* Initialize application
*/
private 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();
});
}
/**
* Set as root the given page and reset content nav (to avoid get back button)
* @param {string} page
*/
public openPage(page: string) {
this.nav.setRoot(page);
}
/**
* Log out of backend, reset token
*/
public logOut(): void {
this.backend.token = '';
this.nav.setRoot(this.rootPage);
}
}

app.component.spec.ts

import { async, TestBed } from '@angular/core/testing';
import {IonicModule, Platform} from 'ionic-angular';
import {PlatformMock, StatusBarMock, SplashScreenMock} from '../../test-config/mocks-ionic';
import {HttpClient} from "@angular/common/http";
import { StatusBar } from '@ionic-native/status-bar';
import { SplashScreen } from '@ionic-native/splash-screen';
import { MyApp } from './app.component';
import {BackendClient} from "../backend/client.service";

describe('MyApp Component', () => {
let fixture;
let component;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [MyApp],
imports: [
IonicModule.forRoot(MyApp),
],
providers: [
{ provide: StatusBar, useClass: StatusBarMock },
{ provide: SplashScreen, useClass: SplashScreenMock },
{ provide: Platform, useClass: PlatformMock },
{ provide: BackendClient },
{ provide: HttpClient},
],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(MyApp);
component = fixture.componentInstance;
// component =
});
it('Initialize MyApp',
() => {
expect(component instanceof MyApp).toBe(true);
});
it('RootPage is equal to LoginPage', () => {
expect(component.rootPage).toBe('LoginPage');
});
// UNIT TEST     who trigger error
it('Log Out reset token',() => {
component.logOut();
expect(component.backend.token).toEqual('');
});
});

失败的测试是第三个"注销重置令牌"。这是似乎触发此错误的文件:

登录.ts

import { Component } from '@angular/core';
import {IonicPage, NavController} from 'ionic-angular';
import {HttpClient} from "@angular/common/http";
import { BackendClient} from "../../backend/client.service";
import { WrongLogin } from "../badlogin/wrong";
@IonicPage()
@Component({
selector: 'page-home',
templateUrl: 'login.html'
})
/**
* Class who manage user login (Homepage of application)
*/
export class LoginPage {
private readonly backend_url: string;
private readonly username: string;
private readonly password: string;
/**
* @param {NavController} navCtrl - navigator controller
* @param {HttpClient} http - http client for backend service
*/
constructor(public navCtrl: NavController, private http: HttpClient
) {
if (localStorage.getItem('url')) {
this.backend_url = localStorage.getItem('url')
}
if (localStorage.getItem('username')) {
this.username = localStorage.getItem('username')
}
}
/**
* Login to backend with current url, username and password
*/
public doLogin(): void {
localStorage.setItem("url", this.backend_url);
localStorage.setItem('username', this.username);
let client = new BackendClient(this.http);
client.login(this.username, this.password)
.subscribe(
function(data) {
localStorage.setItem("token", data['token']);
this.navCtrl.setRoot(LoginPage);
this.navCtrl.setRoot('Dashboard');
}.bind(this),
err => this.navCtrl.push(
WrongLogin, {error: err.message || "Can't join the server."}
)
);
}
}

及其模块文件:

login.module.ts

import { NgModule } from '@angular/core';
import { IonicPageModule } from 'ionic-angular';
import {LoginPage} from "./login";
@NgModule({
declarations: [
LoginPage,
],
imports: [
IonicPageModule.forChild(LoginPage),
],
entryComponents: [
LoginPage
]
})
export class LoginPageModule {}

所以我的类在其模块文件中得到了很好的声明。我已经尝试了许多解决方案和方法,可以在app.component.ts和相应的spec文件中导入此页面,但无事可做,我总是遇到同样的错误:

28 05 2018 10:53:46.411:INFO [Chrome 66.0.3359 (Linux 0.0.0)]: Connected on socket XJsL7iiRTkumZOd9AAAA with id 38260713
....ERROR: 'Unhandled Promise rejection:', 'invalid link: LoginPage', '; Zone:', 'ProxyZone', '; Task:', 'Promise.then', '; Value:', 'invalid link: LoginPage', undefined
ERROR: 'Unhandled Promise rejection:', 'invalid link: LoginPage', '; Zone:', 'ProxyZone', '; Task:', 'Promise.then', '; Value:', 'invalid link: LoginPage', undefined
Chrome 66.0.3359 (Linux 0.0.0): Executed 4 of 4 SUCCESS (1.06 secs / 1.031 secs)

我不明白我的错误是什么...要运行测试,我使用以下命令:

karma start ./test-config/karma.conf.js --single-run

看起来setRoot会尝试导航到不同的页面并返回成功导航的承诺。在您的情况下,该路由可能不存在。测试这一点的一种方法是模拟我认为在这种情况下没有必要的路由,而是您可以测试是否使用正确的参数调用了 setRoot,这可以通过 spyOn 完成。

beforeEach(() => {
fixture = TestBed.createComponent(MyApp);
component = fixture.componentInstance;
spyOn(component.nav, 'setRoot'); 
});
it('Log Out reset token',() => {
component.logOut();
expect(component.backend.token).toEqual('');
expect(component.nav.setRoot).toHaveBeenCalledWith('LoginPage');
});

存根是我们用于测试的一些依赖项的模拟。在您的情况下,Nav是一种依赖关系。您可以在测试中使用Nav的简单模拟/存根,而不是使用 Ionic 的Nav,例如:

component.nav = {setRoot: location=>{}}

另一种方法是使用可能从此页面访问的路由配置测试路由方案: 可以通过以下方式完成:

beforeEach(() => {
TestBed.configureTestModule({
imports: [
RouterTestingModule.withRoutes(
[{path: '', component: BlankCmp}, {path: 'simple', component: SimpleCmp}]
)
]
});
});

此错误是路由错误:

"未处理的承诺拒绝:", "无效链接:登录页面">

表示您尝试重定向到LoginPage,但它不存在。

若要解决此问题,请考虑模拟路由逻辑,而不是使用路由模块。我知道你可以在 Angular 中使用RouterTestingModule,但我不知道 Ionic,对不起。

最新更新