微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

单元测试 – Angular 2单元测试 – 无法读取未定义的属性“root”

错误说明

角度版本:2.3.1

我的单元测试无法创建组件 – 我知道这个问题与[routerLink]和[routerLinkActive]指令有关,因为从模板中删除它们允许测试创建组件.

模板

<nav class="navbar navbar-default navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
  <button class="navbar-toggle" data-toggle="collapse" data-target="#iotahoe-top-navigation">
    <span class="sr-only">Toggle navigation</span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
  </button>
  <a class="navbar-brand" [routerLink]="['/']">IoTahoe</a>
</div>
<div class="collapse navbar-collapse" id="iotahoe-top-navigation">
  <ul *ngIf="isAuthenticated()" class="nav navbar-nav navbar-right">
    <li [routerLinkActive]="['active']"><a [routerLink]="['/dashboard']">Dashboard</a></li>
    <li [routerLinkActive]="['active']"><a [routerLink]="['/browse']">browse</a></li>
    <li [routerLinkActive]="['active']"><a [routerLink]="['/admin']">Admin</a></li>
    <li [routerLinkActive]="['active']"><a (click)="onlogout()" style="cursor: pointer;">logout</a></li>
  </ul>
</div>

打字稿

import { Component,OnInit } from '@angular/core';
import { AuthenticationService } from   '../../authentication/authentication.service';
import { Router } from '@angular/router';

@Component({
moduleId: module.id.toString(),selector: 'app-top-navbar',templateUrl: './top-navbar.component.html',styleUrls: ['./top-navbar.component.css']
})
export class TopNavbarComponent implements OnInit {

constructor(private authenticationService: AuthenticationService,private router: Router) { }

ngOnInit() {
}

isAuthenticated() {
    return this.authenticationService.isLoggedIn;
}

onlogout() {
    this.authenticationService.logout().subscribe(() => {
        return this.router.navigate(['/login']);
    });
}

}

测试规格

/* tslint:disable:no-unused-variable */
import {async,ComponentFixture,Testbed,inject} from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import {DebugElement,CUSTOM_ELEMENTS_SCHEMA,NO_ERRORS_SCHEMA,Component} from '@angular/core';
import { RouterTestingModule } from '@angular/router/testing';
import { Location,CommonModule } from '@angular/common';
import { TopNavbarComponent } from './top-navbar.component';
import { AuthenticationService } from '../../authentication/authentication.service';
import { Router } from '@angular/router';
import {ReactiveFormsModule} from "@angular/forms";

@Component({
template: ''
})
class DummyComponent {
}


describe('TopNavbarComponent',() => {
let component: TopNavbarComponent;
let fixture: ComponentFixture<TopNavbarComponent>;
let authenticationService: AuthenticationService;

beforeEach(async(() => {
    const authenticationServiceStub = {
        isLoggedIn: false
    };

    const routerStub = {
        navigate: jasmine.createSpy('navigate'),navigateByUrl: jasmine.createSpy('navigateByUrl')
    };

    Testbed.configureTestingModule({
        declarations: [ TopNavbarComponent,DummyComponent ],imports:[CommonModule,ReactiveFormsModule,RouterTestingModule.withRoutes(
            [
                { path: '/',component:DummyComponent },{ path: '/login',{ path: '/dashboard',{ path: '/browse',{ path: '/admin',component:DummyComponent }
            ])],providers: [
            { provide: AuthenticationService,useValue: authenticationServiceStub },{ provide: Router,useValue: routerStub }
            ]
    }).compileComponents();
}));

beforeEach(() => {
    fixture = Testbed.createComponent(TopNavbarComponent);
    component = fixture.componentInstance;
    authenticationService = Testbed.get(AuthenticationService);
    fixture.detectChanges();
});

it('should create',() => {
    expect(component).toBeTruthy();
});
});

错误

zone.js:155 Uncaught Error: Error in package:407:9:6 caused by: Cannot
read property ‘root’ of undefined
at ViewWrappedError.Error (native)
at ViewWrappedError.ZoneAwareError (localhost:9876/base/src/test.ts:133296:33)
at ViewWrappedError.BaseError [as constructor] (localhost:9876/base/src/test.ts:35630:16)
at ViewWrappedError.WrappedError [as constructor] (localhost:9876/base/src/test.ts:35695:16)
at new ViewWrappedError (localhost:9876/base/src/test.ts:68018:16)
at DebugAppView._rethrowWithContext (localhost:9876/base/src/test.ts:108242:23)
at DebugAppView.create (localhost:9876/base/src/test.ts:108142:18)
at DebugAppView.View_TopNavbarComponent_Host0.createInternal (/DynamicTestModule/TopNavbarComponent/host.ngfactory.js:16:19)
at DebugAppView.AppView.createHostView (localhost:9876/base/src/test.ts:107700:21)
at DebugAppView.createHostView (localhost:9876/base/src/test.ts:108156:52)
at ComponentFactory.create (localhost:9876/base/src/test.ts:49830:25)
at initComponent (localhost:9876/base/src/test.ts:6425:53)
at ZoneDelegate.invoke (localhost:9876/base/src/test.ts:132727:26)
at ProxyZonespec.onInvoke (localhost:9876/base/src/test.ts:95802:39)
at ZoneDelegate.invoke (localhost:9876/base/src/test.ts:132726:32)Zone.runTask @
zone.js:155ZoneTask.invoke @ zone.js:345data.args.(anonymous function)
@ zone.js:1376

routerLink指令需要一个真正的路由器,但你正在嘲笑它.我能看到你做的几件事:

>如果您不打算在测试期间单击链接,那么您可以模拟这些指令只是制作“noop”指令,因此编译器不会抱怨.例如

@Directive({
    selector: '[routerLink],[routerLinkActive]'
})
class DummyRouterLinkDirective {}

然后将其添加到测试模块的声明中.有了这个,你根本不需要配置RouterTestingModule.你可以摆脱它.
>此外,如果您不打算单击测试,另一个选项(无需创建伪指令)只是忽略缺失指令的错误

schemas: [ NO_ERRORS_SCHEMA ]

您可以将其添加到测试模块配置中(如here所示).在某些情况下,这可能是不可取的,因为它也可能忽略您实际想要检测到的错误,这可能导致难以调试测试.
>如果您真的想单击链接并测试路由,那么您可以使用真正的路由器.您可以使用位置查看如何测试导航的示例,如this post所示.

原文地址:https://www.jb51.cc/angularjs/143591.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐