角度测试路由器参数打破测试台



当我为我的TestComponent提供参数时,如果html包含[routerLink],测试台就会爆炸

测试平台设置

TestBed.configureTestingModule({
imports: [SharedModule.forRoot(), ManagementModule, HttpModule, RouterModule.forRoot([{
path: '', component: TestComponent
}])],
declarations: [TestComponent],
providers: [
BaseRequestOptions,
MockBackend,
{
provide: Http, useFactory: function (backend: MockBackend, defaultOptions: BaseRequestOptions) {
return new Http(backend, defaultOptions);
},
deps: [MockBackend, BaseRequestOptions]
},
{ provide: APP_BASE_HREF, useValue: '/' },
{
provide: ActivatedRoute,
useValue: {
params: Observable.of({ versionId: '1' }),
parent: {
params: Observable.of({ uniqueId: '1234' })
}
}
}
]
});
TestBed.compileComponents();
});

记录的错误

Failed: Error in ./DetailComponent class DetailComponent - inline template:72:20 caused by: Cannot read property '_lastPathIndex' of undefined
TypeError: Cannot read property '_lastPathIndex' of undefined
at findStartingPosition (webpack:///home/developer/Projects/project/~/@angular/router/src/create_url_tree.js:184:0 <- src/test.ts:100429:23)
at createUrlTree (webpack:///home/developer/Projects/project/~/@angular/router/src/create_url_tree.js:27:21 <- src/test.ts:100272:45)
at Router.createUrlTree (webpack:///home/developer/Projects/project/~/@angular/router/src/router.js:424:0 <- src/test.ts:28688:111)
at RouterLinkWithHref.get [as urlTree] (webpack:///home/developer/Projects/project/~/@angular/router/src/directives/router_link.js:253:0 <- src/test.ts:50778:32)
at RouterLinkWithHref.updateTargetUrlAndHref (webpack:///home/developer/Projects/project/~/@angular/router/src/directives/router_link.js:246:0 <- src/test.ts:50771:91)
at RouterLinkWithHref.ngOnChanges (webpack:///home/developer/Projects/project/~/@angular/router/src/directives/router_link.js:217:67 <- src/test.ts:50742:74)
at Wrapper_RouterLinkWithHref.ngDoCheck (/RouterModule/RouterLinkWithHref/wrapper.ngfactory.js:101:18)
at DebugAppView.View_DetailComponent3.detectChangesInternal (/ManagementModule/DetailComponent/component.ngfactory.js:548:33)
at DebugAppView.AppView.detectChanges (webpack:///home/developer/Projects/project/~/@angular/core/src/linker/view.js:425:0 <- src/test.ts:95635:14)
at DebugAppView.detectChanges (webpack:///home/developer/Projects/project/~/@angular/core/src/linker/view.js:620:0 <- src/test.ts:95830:44)
at ViewContainer.detectChangesInNestedViews (webpack:///home/developer/Projects/project/~/@angular/core/src/linker/view_container.js:67:0 <- src/test.ts:95967:37)
at DebugAppView.View_DetailComponent0.detectChangesInternal (/ManagementModule/DetailComponent/component.ngfactory.js:85:14)
at DebugAppView.AppView.detectChanges (webpack:///home/developer/Projects/project/~/@angular/core/src/linker/view.js:425:0 <- src/test.ts:95635:14)
at DebugAppView.detectChanges (webpack:///home/developer/Projects/project/~/@angular/core/src/linker/view.js:620:0 <- src/test.ts:95830:44)

模板行 72

<a class="button" [routerLink]="['/']">Back</a>

在一个理想的世界中,我想继续提供参数,知道它为什么会爆炸吗?

我想出了问题/解决方案。

我们看到Cannot read property '_lastPathIndex' of undefined,因为 Angular 路由器在某一时刻期望在snapshot对象上具有_lastPathIndex属性。

Angular 源代码的相关部分如下所示:

if (route.snapshot._lastPathIndex === -1) {
return new Position(route.snapshot._urlSegment, true, 0);
}

如果snapshot未定义,它当然会引发我们看到的错误。

这个问题可以通过使snapshot不定义来解决。

这是我是如何做到的。我的代码与OP的代码略有不同。

我有一个名为MockActivatedRoute的类,看起来像这样。

export class MockActivatedRoute {
parent: any;
params: any;
constructor(options) {
this.parent = options.parent;
this.params = options.params;
}
}

以下是我在测试中使用它的方式。

let mockActivatedRoute = new MockActivatedRoute({
parent: new MockActivatedRoute({
params: Observable.of({ id: '1' })
})
});

为了使错误消失,我只是在MockActivatedRoute中添加了一个snapshot属性。

export class MockActivatedRoute {
parent: any;
params: any;
snapshot = {};
constructor(options) {
this.parent = options.parent;
this.params = options.params;
}
}

您可以在提供程序数组中添加快照属性。

providers: [{ provide: ActivatedRoute, useValue: { snapshot: {} } }]

将快照添加到您的 ActiveRoute,将 Value Object 与参数一起使用。

providers: [
{
provide: ActivatedRoute, useValue: {
params: of({ id: 'test' }),
snapshot: {}
}
},
]

这没有错误,也没有黑客

import {
TestBed,
async
} from '@angular/core/testing';
import {
HttpModule,
BaseRequestOptions,
Http
} from '@angular/http';
import { APP_BASE_HREF } from '@angular/common';
import {
RouterModule,
ActivatedRoute
} from '@angular/router';
import { MockBackend } from '@angular/http/testing';
import { Observable } from 'rxjs';
import { Component } from '@angular/core';
fdescribe( 'AppComponent', () => {
beforeEach( () => {
TestBed.configureTestingModule( {
imports      : [
HttpModule,
RouterModule.forRoot(
[
{
path      : '',
component : TestComponent
}
] )
],
declarations : [ TestComponent ],
providers    : [
BaseRequestOptions,
MockBackend,
{
provide    : Http,
useFactory : function ( backend : MockBackend, defaultOptions : BaseRequestOptions ) {
return new Http( backend, defaultOptions );
},
deps       : [ MockBackend, BaseRequestOptions ]
},
{
provide  : APP_BASE_HREF,
useValue : '/'
},
{
provide  : ActivatedRoute,
useValue : {
params : Observable.of( { versionId : '1' } ),
parent : {
params : Observable.of( { uniqueId : '1234' } )
}
}
}
]
} );
TestBed.compileComponents();
} );
it( 'should create the app', async( () => {
let fixture = TestBed.createComponent( TestComponent );
let app     = fixture.debugElement.componentInstance;
expect( app ).toBeTruthy();
} ) );
} );
@Component( {
selector    : 'app-root',
template : `
<a class="button" [routerLink]="['/']">Back</a>
<router-outlet></router-outlet>
`,
} )
export class TestComponent {
}

最新更新