在 Angular 中测试没有插座的路线导航
Testing route navigation without an outlet in Angular
我正在为一个 Angular 组件编写规范,该组件显示一个可以导航到另一个页面的按钮。该组件使用 Router::navigate()
但本身没有路由器插座。父组件有出口。在我的规范中,测试应该确认点击按钮路由到正确的路径。
我当前的(损坏的)规范尝试使用 RouterTestingModule
提供通往 DummyComponent
的路径。在规范中单击按钮时,出现以下错误:
'Unhandled Promise rejection:', 'Cannot find primary outlet to load 'DummyComponent'', '; Zone:', 'angular', '; Task:', 'Promise.then', '; Value:', Error{__zone_symbol__error: Error{originalStack: 'Error: Cannot find primary outlet to load 'DummyComponent'
显然我以错误的方式解决了这个问题。当组件没有路由器插座时,测试路由器导航的正确方法是什么?
组件(伪代码):
@Component({
template: `
Go to the <button (click)="nextPage">next page</button>
`
})
export class ExampleComponent {
public myId = 5;
constructor(private _router: Router);
public nextPage(): void {
this._router.navigate(['/example', this.myId]);
}
}
规格。这不起作用:
const FAKE_ID = 999;
describe('ExampleComponent Test', () => {
let exampleComponent: ExampleComponent;
let fixture: ComponentFixture<ExampleComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ DummyComponent ],
imports: [
RouterTestingModule.withRoutes([
{ path: 'example/:id', component: DummyComponent }
]);
]
});
fixture = TestBed.createComponent(exampleComponent);
exampleComponent = fixture.componentInstance;
});
it('should route to example/:id', inject([Router, Location], (router: Router, location: Location) => {
fixture.detectChanges();
exampleComponent.myId = FAKE_ID;
const LINK_BUTTON = fixture.debugElement.query(By.css('button'));
LINK_BUTTON.nativeElement.dispatchEvent(new Event('click'));
expect(location.path()).toEqual('/example/' + FAKE_ID);
});
});
DummyComponent
需要一个插座 (<router-outlet>
)。如果 DummyComponent
是从 ExampleComponent
导航到的路线,那么 ExampleComponent
应该有出口。您还需要将 ExampleComponent
添加到声明中`
@Component({
tempalte: `
<router-outlet></router-outlet>
<button (click)="nextPage">next page</button>
`
})
class ExampleComponent{}
declarations: [ ExampleComponent, DummyComponent ]
如果您想避免仅仅为了测试导航到的路由而必须设置此基础结构,更好的选择可能是仅模拟 Router
,并检查 navigate
使用正确的路径调用方法。
beforeEach(()=>{
TestBed.configureTestingModule({
providers: [
{
provide: Router,
useValue: { navigate: jasmine.createSpy('navigate') }
}
]
})
})
有了这个,您根本不需要配置路由,因为您使用的是假 Router
。然后在你的测试中
it('should route to example/:id', inject([Router], (router: Router) => {
expect(router.navigate).toHaveBeenCalledWith(['/example', FAKE_ID]);
});
我正在为一个 Angular 组件编写规范,该组件显示一个可以导航到另一个页面的按钮。该组件使用 Router::navigate()
但本身没有路由器插座。父组件有出口。在我的规范中,测试应该确认点击按钮路由到正确的路径。
我当前的(损坏的)规范尝试使用 RouterTestingModule
提供通往 DummyComponent
的路径。在规范中单击按钮时,出现以下错误:
'Unhandled Promise rejection:', 'Cannot find primary outlet to load 'DummyComponent'', '; Zone:', 'angular', '; Task:', 'Promise.then', '; Value:', Error{__zone_symbol__error: Error{originalStack: 'Error: Cannot find primary outlet to load 'DummyComponent'
显然我以错误的方式解决了这个问题。当组件没有路由器插座时,测试路由器导航的正确方法是什么?
组件(伪代码):
@Component({
template: `
Go to the <button (click)="nextPage">next page</button>
`
})
export class ExampleComponent {
public myId = 5;
constructor(private _router: Router);
public nextPage(): void {
this._router.navigate(['/example', this.myId]);
}
}
规格。这不起作用:
const FAKE_ID = 999;
describe('ExampleComponent Test', () => {
let exampleComponent: ExampleComponent;
let fixture: ComponentFixture<ExampleComponent>;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [ DummyComponent ],
imports: [
RouterTestingModule.withRoutes([
{ path: 'example/:id', component: DummyComponent }
]);
]
});
fixture = TestBed.createComponent(exampleComponent);
exampleComponent = fixture.componentInstance;
});
it('should route to example/:id', inject([Router, Location], (router: Router, location: Location) => {
fixture.detectChanges();
exampleComponent.myId = FAKE_ID;
const LINK_BUTTON = fixture.debugElement.query(By.css('button'));
LINK_BUTTON.nativeElement.dispatchEvent(new Event('click'));
expect(location.path()).toEqual('/example/' + FAKE_ID);
});
});
DummyComponent
需要一个插座 (<router-outlet>
)。如果 DummyComponent
是从 ExampleComponent
导航到的路线,那么 ExampleComponent
应该有出口。您还需要将 ExampleComponent
添加到声明中`
@Component({
tempalte: `
<router-outlet></router-outlet>
<button (click)="nextPage">next page</button>
`
})
class ExampleComponent{}
declarations: [ ExampleComponent, DummyComponent ]
如果您想避免仅仅为了测试导航到的路由而必须设置此基础结构,更好的选择可能是仅模拟 Router
,并检查 navigate
使用正确的路径调用方法。
beforeEach(()=>{
TestBed.configureTestingModule({
providers: [
{
provide: Router,
useValue: { navigate: jasmine.createSpy('navigate') }
}
]
})
})
有了这个,您根本不需要配置路由,因为您使用的是假 Router
。然后在你的测试中
it('should route to example/:id', inject([Router], (router: Router) => {
expect(router.navigate).toHaveBeenCalledWith(['/example', FAKE_ID]);
});