未处理的承诺拒绝:无法匹配任何路线
Unhandled Promise rejection: Cannot match any routes
当我运行这个单元测试时:
it('can click profile link in template', () => {
const landingPageLinkDe = linkDes[0];
const profileLinkDe = linkDes[1];
const aboutLinkDe = linkDes[2];
const findLinkDe = linkDes[3];
const addLinkDe = linkDes[4];
const registerLinkDe = linkDes[5];
const landingPageLinkFull = links[0];
const profileLinkFull = links[1];
const aboutLinkFull = links[2];
const findLinkFull = links[3];
const addLinkFull = links[4];
const registerLinkFull = links[5];
navFixture.detectChanges();
expect(profileLinkFull.navigatedTo)
.toBeNull('link should not have navigated yet');
profileLinkDe.triggerEventHandler('click', { button: 0 });
landingPageLinkDe.triggerEventHandler('click', { button: 0 });
aboutLinkDe.triggerEventHandler('click', { button: 0 });
registerLinkDe.triggerEventHandler('click', { button: 0 });
findLinkDe.triggerEventHandler('click', { button: 0 });
addLinkDe.triggerEventHandler('click', { button: 0 });
navFixture.detectChanges();
expect(landingPageLinkFull.navigatedTo).toBe('/');
expect(profileLinkFull.navigatedTo).toBe('/profile');
expect(aboutLinkFull.navigatedTo).toBe('/about');
expect(findLinkFull.navigatedTo).toBe('/find');
expect(addLinkFull.navigatedTo).toBe('/add');
expect(registerLinkFull.navigatedTo).toBe('/register');
});
我收到这个错误:
zone.js:388 Unhandled Promise rejection: Cannot match any routes. URL
Segment: 'add' ; Zone: ProxyZone ; Task: Promise.then ; Value: Error:
Cannot match any routes. URL Segment: 'add'(…) Error: Cannot match any
routes. URL Segment: 'add'
测试仍然通过,但我很想知道为什么会出现错误。当我像用户一样使用应用程序时,我没有收到错误。我研究了这个错误,这通常是由于没有在路由中提供默认路径,但我已经做到了。
我是不是做错了什么导致这个错误?
navbar.component.spec.ts
import 'zone.js/dist/long-stack-trace-zone.js';
import 'zone.js/dist/async-test.js';
import 'zone.js/dist/fake-async-test.js';
import 'zone.js/dist/sync-test.js';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/jasmine-patch.js';
import {
ComponentFixture,
TestBed,
async,
fakeAsync
} from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { By } from '@angular/platform-browser';
import {
DebugElement,
Component,
ViewChild,
Pipe,
PipeTransform,
CUSTOM_ELEMENTS_SCHEMA,
NO_ERRORS_SCHEMA
} from '@angular/core';
import { DatePipe } from '@angular/common';
import { Router, RouterOutlet, RouterModule } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { NavbarComponent } from './navbar.component';
import { RouterLinkStubDirective } from '../../router-stubs';
import { click } from '../../test/utilities.spec';
describe('NavbarComponent', () => {
let navComponent: NavbarComponent;
let navFixture: ComponentFixture<NavbarComponent>;
let linkDes: any;
let links: any;
let landingPageLink: any;
let profileLink: any;
let aboutLink: any;
let findLink: any;
let addLink: any;
let registerLink: any;
beforeAll(() => {
TestBed.resetTestEnvironment();
TestBed.initTestEnvironment(BrowserDynamicTestingModule,
platformBrowserDynamicTesting());
});
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
NavbarComponent,
RouterLinkStubDirective
],
imports: [RouterTestingModule],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
navFixture = TestBed.createComponent(NavbarComponent);
navComponent = navFixture.componentInstance;
navFixture.detectChanges();
linkDes = navFixture.debugElement
.queryAll(By.directive(RouterLinkStubDirective));
links = linkDes
.map((de: any) => de.injector
.get(RouterLinkStubDirective) as RouterLinkStubDirective);
landingPageLink = links[0].linkParams;
profileLink = links[1].linkParams;
aboutLink = links[2].linkParams;
findLink = links[3].linkParams;
addLink = links[4].linkParams;
registerLink = links[5].linkParams;
});
it('can get RouterLinks from template', () => {
expect(links.length).toBe(6, 'should have 6 links');
expect(landingPageLink[0])
.toEqual('/', '1st link should go to landing page');
expect(profileLink[0])
.toEqual('/profile', '2nd link should go to profile');
expect(aboutLink[0])
.toEqual('/about', '3rd link should go to about');
expect(findLink[0])
.toEqual('/find', '4th link should go to find');
expect(addLink[0])
.toEqual('/add', '5th link should go to add');
expect(registerLink[0])
.toEqual('/register', '6th link should go to register');
});
it('can click profile link in template', () => {
const landingPageLinkDe = linkDes[0];
const profileLinkDe = linkDes[1];
const aboutLinkDe = linkDes[2];
const findLinkDe = linkDes[3];
const addLinkDe = linkDes[4];
const registerLinkDe = linkDes[5];
const landingPageLinkFull = links[0];
const profileLinkFull = links[1];
const aboutLinkFull = links[2];
const findLinkFull = links[3];
const addLinkFull = links[4];
const registerLinkFull = links[5];
navFixture.detectChanges();
expect(profileLinkFull.navigatedTo)
.toBeNull('link should not have navigated yet');
profileLinkDe.triggerEventHandler('click', { button: 0 });
landingPageLinkDe.triggerEventHandler('click', { button: 0 });
aboutLinkDe.triggerEventHandler('click', { button: 0 });
registerLinkDe.triggerEventHandler('click', { button: 0 });
findLinkDe.triggerEventHandler('click', { button: 0 });
addLinkDe.triggerEventHandler('click', { button: 0 });
navFixture.detectChanges();
expect(landingPageLinkFull.navigatedTo).toBe('/');
expect(profileLinkFull.navigatedTo).toBe('/profile');
expect(aboutLinkFull.navigatedTo).toBe('/about');
expect(findLinkFull.navigatedTo).toBe('/find');
expect(addLinkFull.navigatedTo).toBe('/add');
expect(registerLinkFull.navigatedTo).toBe('/register');
});
});
测试存根:
import 'zone.js/dist/long-stack-trace-zone.js';
import 'zone.js/dist/async-test.js';
import 'zone.js/dist/fake-async-test.js';
import 'zone.js/dist/sync-test.js';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/jasmine-patch.js';
import {
EventEmitter,
Output,
trigger,
state,
style,
transition,
animate,
Directive,
Input
} from '@angular/core';
import {
ComponentFixture,
TestBed,
async,
fakeAsync
} from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { By } from '@angular/platform-browser';
import {
DebugElement,
Component,
ViewChild,
Pipe,
PipeTransform
} from '@angular/core';
import { DatePipe } from '@angular/common';
import { Router } from '@angular/router';
import { NavbarComponent } from './shared/subcomponents/navbar.component';
import { AppComponent } from './app.component';
import { click } from './test/utilities.spec';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
@Directive({
selector: '[routerLink]',
host: {
'(click)': 'onClick()'
}
})
export class RouterLinkStubDirective {
@Input('routerLink') linkParams: any;
navigatedTo: any = null;
onClick() {
this.navigatedTo = this.linkParams[0];
}
}
app.routes.ts:
import { Routes } from '@angular/router';
import { LandingPageComponent } from './landing-page/landing-page.component';
import { FindPageComponent } from './find-page/find-page.component';
import { AddPageComponent } from './add-page/add-page.component';
import { RegisterPageComponent } from './register-page/register-page.component';
import { AboutPageComponent } from './about-page/about-page.component';
import { ProfilePageComponent } from './profile-page/profile-page.component';
export const routerConfig: Routes = [
{
path: '',
component: LandingPageComponent
},
{
path: '',
redirectTo: '',
pathMatch: 'full'
},
{
path: 'find',
component: FindPageComponent
},
{
path: 'add',
component: AddPageComponent
},
{
path: 'register',
component: RegisterPageComponent
},
{
path: 'about',
component: AboutPageComponent
},
{
path: 'profile',
component: ProfilePageComponent
}
];
navbar.component.html:
<nav class="navbar navbar-dark navbar-fixed-top text-uppercase">
<div class="container-fluid">
<button class="navbar-toggler hidden-md-up pull-xs-right"
type="button"
data-toggle="collapse"
data-target="#nav-content">
☰
</button>
<a class="navbar-brand" [routerLink]="['/']"
routerLinkActive="active">vepo</a>
<div class="collapse navbar-toggleable-sm" id="nav-content">
<ul class="nav navbar-nav pull-xs-right">
<li class="nav-item">
<a class="nav-link" [routerLink]="['/profile']"
routerLinkActive="active">profile</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['/about']"
routerLinkActive="active">about</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['/find']"
routerLinkActive="active">find</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['/add']"
routerLinkActive="active">add</a>
</li>
<li class="nav-item">
<button type="button" class="as-text nav-link
text-uppercase" (click)="openModal()">
login
</button>
</li>
<li class="nav-item">
<a class="nav-link signup" [routerLink]="['/register']"
routerLinkActive="active">sign up free</a>
</li>
</ul>
</div>
</div>
</nav>
<login #modal></login>
<router-outlet></router-outlet>
我最近遇到了同样的问题。这是由在组件的 ngOnInit
方法中调用 router.navigate
引起的。测试试图创建组件,但在 ngOnInit
内部它试图离开组件(因为不满足某些条件)。
在我的例子中,我将 RouterTestingModule
作为 TestBed.configureTestingModule
的一部分导入。所以为了解决这个问题,我只是用 RouterTestingModule
注册了一条路线。例如,假设您的导航调用看起来像 router.navigate(['example'])
,它解析为 ExampleComponent
。您可以按如下方式设置测试:
RouterTestingModule.withRoutes([
{ path: 'example', component: ExampleComponent}
])
执行上述操作允许我的测试 运行 而不会发出 Cannot match any routes
错误。
就其价值而言,我认为更好的方法是对路由器进行存根并确认对 navigate
进行了适当的调用。
为了稍微扩展 spoida 的回答,我最终使用了一个存根路由器:
class RouterStub {
url = '';
navigate(commands: any[], extras?: any) { }
}
然后在您的提供商中进行测试:
providers: [
{ provide: Router, useClass: RouterStub }
// ... other providers
]
这导致我的单元测试仍然通过并消除了我看到的控制台错误。
当我运行这个单元测试时:
it('can click profile link in template', () => {
const landingPageLinkDe = linkDes[0];
const profileLinkDe = linkDes[1];
const aboutLinkDe = linkDes[2];
const findLinkDe = linkDes[3];
const addLinkDe = linkDes[4];
const registerLinkDe = linkDes[5];
const landingPageLinkFull = links[0];
const profileLinkFull = links[1];
const aboutLinkFull = links[2];
const findLinkFull = links[3];
const addLinkFull = links[4];
const registerLinkFull = links[5];
navFixture.detectChanges();
expect(profileLinkFull.navigatedTo)
.toBeNull('link should not have navigated yet');
profileLinkDe.triggerEventHandler('click', { button: 0 });
landingPageLinkDe.triggerEventHandler('click', { button: 0 });
aboutLinkDe.triggerEventHandler('click', { button: 0 });
registerLinkDe.triggerEventHandler('click', { button: 0 });
findLinkDe.triggerEventHandler('click', { button: 0 });
addLinkDe.triggerEventHandler('click', { button: 0 });
navFixture.detectChanges();
expect(landingPageLinkFull.navigatedTo).toBe('/');
expect(profileLinkFull.navigatedTo).toBe('/profile');
expect(aboutLinkFull.navigatedTo).toBe('/about');
expect(findLinkFull.navigatedTo).toBe('/find');
expect(addLinkFull.navigatedTo).toBe('/add');
expect(registerLinkFull.navigatedTo).toBe('/register');
});
我收到这个错误:
zone.js:388 Unhandled Promise rejection: Cannot match any routes. URL Segment: 'add' ; Zone: ProxyZone ; Task: Promise.then ; Value: Error: Cannot match any routes. URL Segment: 'add'(…) Error: Cannot match any routes. URL Segment: 'add'
测试仍然通过,但我很想知道为什么会出现错误。当我像用户一样使用应用程序时,我没有收到错误。我研究了这个错误,这通常是由于没有在路由中提供默认路径,但我已经做到了。
我是不是做错了什么导致这个错误?
navbar.component.spec.ts
import 'zone.js/dist/long-stack-trace-zone.js';
import 'zone.js/dist/async-test.js';
import 'zone.js/dist/fake-async-test.js';
import 'zone.js/dist/sync-test.js';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/jasmine-patch.js';
import {
ComponentFixture,
TestBed,
async,
fakeAsync
} from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { By } from '@angular/platform-browser';
import {
DebugElement,
Component,
ViewChild,
Pipe,
PipeTransform,
CUSTOM_ELEMENTS_SCHEMA,
NO_ERRORS_SCHEMA
} from '@angular/core';
import { DatePipe } from '@angular/common';
import { Router, RouterOutlet, RouterModule } from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { NavbarComponent } from './navbar.component';
import { RouterLinkStubDirective } from '../../router-stubs';
import { click } from '../../test/utilities.spec';
describe('NavbarComponent', () => {
let navComponent: NavbarComponent;
let navFixture: ComponentFixture<NavbarComponent>;
let linkDes: any;
let links: any;
let landingPageLink: any;
let profileLink: any;
let aboutLink: any;
let findLink: any;
let addLink: any;
let registerLink: any;
beforeAll(() => {
TestBed.resetTestEnvironment();
TestBed.initTestEnvironment(BrowserDynamicTestingModule,
platformBrowserDynamicTesting());
});
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
NavbarComponent,
RouterLinkStubDirective
],
imports: [RouterTestingModule],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
navFixture = TestBed.createComponent(NavbarComponent);
navComponent = navFixture.componentInstance;
navFixture.detectChanges();
linkDes = navFixture.debugElement
.queryAll(By.directive(RouterLinkStubDirective));
links = linkDes
.map((de: any) => de.injector
.get(RouterLinkStubDirective) as RouterLinkStubDirective);
landingPageLink = links[0].linkParams;
profileLink = links[1].linkParams;
aboutLink = links[2].linkParams;
findLink = links[3].linkParams;
addLink = links[4].linkParams;
registerLink = links[5].linkParams;
});
it('can get RouterLinks from template', () => {
expect(links.length).toBe(6, 'should have 6 links');
expect(landingPageLink[0])
.toEqual('/', '1st link should go to landing page');
expect(profileLink[0])
.toEqual('/profile', '2nd link should go to profile');
expect(aboutLink[0])
.toEqual('/about', '3rd link should go to about');
expect(findLink[0])
.toEqual('/find', '4th link should go to find');
expect(addLink[0])
.toEqual('/add', '5th link should go to add');
expect(registerLink[0])
.toEqual('/register', '6th link should go to register');
});
it('can click profile link in template', () => {
const landingPageLinkDe = linkDes[0];
const profileLinkDe = linkDes[1];
const aboutLinkDe = linkDes[2];
const findLinkDe = linkDes[3];
const addLinkDe = linkDes[4];
const registerLinkDe = linkDes[5];
const landingPageLinkFull = links[0];
const profileLinkFull = links[1];
const aboutLinkFull = links[2];
const findLinkFull = links[3];
const addLinkFull = links[4];
const registerLinkFull = links[5];
navFixture.detectChanges();
expect(profileLinkFull.navigatedTo)
.toBeNull('link should not have navigated yet');
profileLinkDe.triggerEventHandler('click', { button: 0 });
landingPageLinkDe.triggerEventHandler('click', { button: 0 });
aboutLinkDe.triggerEventHandler('click', { button: 0 });
registerLinkDe.triggerEventHandler('click', { button: 0 });
findLinkDe.triggerEventHandler('click', { button: 0 });
addLinkDe.triggerEventHandler('click', { button: 0 });
navFixture.detectChanges();
expect(landingPageLinkFull.navigatedTo).toBe('/');
expect(profileLinkFull.navigatedTo).toBe('/profile');
expect(aboutLinkFull.navigatedTo).toBe('/about');
expect(findLinkFull.navigatedTo).toBe('/find');
expect(addLinkFull.navigatedTo).toBe('/add');
expect(registerLinkFull.navigatedTo).toBe('/register');
});
});
测试存根:
import 'zone.js/dist/long-stack-trace-zone.js';
import 'zone.js/dist/async-test.js';
import 'zone.js/dist/fake-async-test.js';
import 'zone.js/dist/sync-test.js';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/jasmine-patch.js';
import {
EventEmitter,
Output,
trigger,
state,
style,
transition,
animate,
Directive,
Input
} from '@angular/core';
import {
ComponentFixture,
TestBed,
async,
fakeAsync
} from '@angular/core/testing';
import {
BrowserDynamicTestingModule,
platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { By } from '@angular/platform-browser';
import {
DebugElement,
Component,
ViewChild,
Pipe,
PipeTransform
} from '@angular/core';
import { DatePipe } from '@angular/common';
import { Router } from '@angular/router';
import { NavbarComponent } from './shared/subcomponents/navbar.component';
import { AppComponent } from './app.component';
import { click } from './test/utilities.spec';
import { FormsModule, ReactiveFormsModule } from '@angular/forms'
@Directive({
selector: '[routerLink]',
host: {
'(click)': 'onClick()'
}
})
export class RouterLinkStubDirective {
@Input('routerLink') linkParams: any;
navigatedTo: any = null;
onClick() {
this.navigatedTo = this.linkParams[0];
}
}
app.routes.ts:
import { Routes } from '@angular/router';
import { LandingPageComponent } from './landing-page/landing-page.component';
import { FindPageComponent } from './find-page/find-page.component';
import { AddPageComponent } from './add-page/add-page.component';
import { RegisterPageComponent } from './register-page/register-page.component';
import { AboutPageComponent } from './about-page/about-page.component';
import { ProfilePageComponent } from './profile-page/profile-page.component';
export const routerConfig: Routes = [
{
path: '',
component: LandingPageComponent
},
{
path: '',
redirectTo: '',
pathMatch: 'full'
},
{
path: 'find',
component: FindPageComponent
},
{
path: 'add',
component: AddPageComponent
},
{
path: 'register',
component: RegisterPageComponent
},
{
path: 'about',
component: AboutPageComponent
},
{
path: 'profile',
component: ProfilePageComponent
}
];
navbar.component.html:
<nav class="navbar navbar-dark navbar-fixed-top text-uppercase">
<div class="container-fluid">
<button class="navbar-toggler hidden-md-up pull-xs-right"
type="button"
data-toggle="collapse"
data-target="#nav-content">
☰
</button>
<a class="navbar-brand" [routerLink]="['/']"
routerLinkActive="active">vepo</a>
<div class="collapse navbar-toggleable-sm" id="nav-content">
<ul class="nav navbar-nav pull-xs-right">
<li class="nav-item">
<a class="nav-link" [routerLink]="['/profile']"
routerLinkActive="active">profile</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['/about']"
routerLinkActive="active">about</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['/find']"
routerLinkActive="active">find</a>
</li>
<li class="nav-item">
<a class="nav-link" [routerLink]="['/add']"
routerLinkActive="active">add</a>
</li>
<li class="nav-item">
<button type="button" class="as-text nav-link
text-uppercase" (click)="openModal()">
login
</button>
</li>
<li class="nav-item">
<a class="nav-link signup" [routerLink]="['/register']"
routerLinkActive="active">sign up free</a>
</li>
</ul>
</div>
</div>
</nav>
<login #modal></login>
<router-outlet></router-outlet>
我最近遇到了同样的问题。这是由在组件的 ngOnInit
方法中调用 router.navigate
引起的。测试试图创建组件,但在 ngOnInit
内部它试图离开组件(因为不满足某些条件)。
在我的例子中,我将 RouterTestingModule
作为 TestBed.configureTestingModule
的一部分导入。所以为了解决这个问题,我只是用 RouterTestingModule
注册了一条路线。例如,假设您的导航调用看起来像 router.navigate(['example'])
,它解析为 ExampleComponent
。您可以按如下方式设置测试:
RouterTestingModule.withRoutes([
{ path: 'example', component: ExampleComponent}
])
执行上述操作允许我的测试 运行 而不会发出 Cannot match any routes
错误。
就其价值而言,我认为更好的方法是对路由器进行存根并确认对 navigate
进行了适当的调用。
为了稍微扩展 spoida 的回答,我最终使用了一个存根路由器:
class RouterStub {
url = '';
navigate(commands: any[], extras?: any) { }
}
然后在您的提供商中进行测试:
providers: [
{ provide: Router, useClass: RouterStub }
// ... other providers
]
这导致我的单元测试仍然通过并消除了我看到的控制台错误。