如何使用 RouterTestingModule 测试路由导航
How to test routing navigation with RouterTestingModule
我想测试将我发送到特定页面的方法。我检查了几个示例,所有示例都按照我所做的相同方式完成,但我收到错误消息:
预期间谍导航已被调用:
['/主题']
但它从未被调用过。
错误:预期的间谍导航已被调用:
['/主题']
但它从未被调用过。
我的html代码是:
<button class="arrow-back-icon kf-tooltip-btn align-middle" id="backButton"
tabindex="0" name="ic_arrow-back_24" (click)="goBack()">
</button>
我组件中的方法是:
import {AfterViewChecked, ChangeDetectorRef, Component, OnInit} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import {SharingDataService} from '../services/sharing-data.service';
import {ActivatedRoute, Router} from '@angular/router';
import {BreakpointObserver} from '@angular/cdk/layout';
@Component({
selector: 'app-meeting',
templateUrl: './meeting.component.html',
styleUrls: ['./meeting.component.scss']
})
export class MeetingComponent implements OnInit, AfterViewChecked {
constructor(private readonly translate: TranslateService,
private readonly sharingDataService: SharingDataService,
private readonly router: Router,
private readonly activatedRoute: ActivatedRoute,
private readonly breakpointObserver: BreakpointObserver,
private readonly cd: ChangeDetectorRef) {
}
goBack(): void {
this.router.navigate(['/themen']).then();
}
}
测试是:
import {ComponentFixture, fakeAsync, inject, TestBed, waitForAsync} from '@angular/core/testing';
import {MeetingComponent} from './meeting.component';
import {Router, Routes} from '@angular/router';
import {CommonModule} from '@angular/common';
import {RouterTestingModule} from '@angular/router/testing';
import {TranslateLocalModule} from '../../../projects/shared/src/lib/translate';
describe('MeetingComponent', () => {
let sut: meetingComponent;
let fixture: ComponentFixture<MeetingComponent>;
const routes: Routes = [
{path: '', redirectTo: 'themen', pathMatch: 'full'},
{path: 'meeting', component: meetingComponent},
{path: '**', redirectTo: 'themen', pathMatch: 'full'}
];
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MeetingComponent ],
imports: [
CommonModule,
RouterTestingModule.withRoutes(routes),
TranslateLocalModule,
providers: [
]
}).compileComponents();
});
beforeEach(() => {fixture = TestBed.createComponent(MeetingComponent);
sut = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(sut).toBeTruthy();
});
it('should go on previous step', waitForAsync(() => {
const routerSpy = {
navigate: jasmine.createSpy('navigate')
};
sut.onPrevStep();
fixture.detectChanges();
expect (routerSpy.navigate).toHaveBeenCalledWith('/themen');
}));
});
谁能告诉我我做错了什么?
我也试过这个:
it('should navigates to previous step', fakeAsync(async () => {
spyOn(sut, 'onPrevStep').and.returnValue(await Promise.resolve());
const navigateSpy = spyOn(router, 'navigate');
sut.onPrevStep();
tick();
expect(sut.onPrevStep).toHaveBeenCalled();
expect(navigateSpy).toHaveBeenCalledWith(['/themen']);
}));
但是错误还是一样
谢谢!
是的,我认为您的 routerSpy
未与路由器相关联。
关注评论!!
试试这个:
import {ComponentFixture, fakeAsync, inject, TestBed, waitForAsync} from '@angular/core/testing';
import {MeetingComponent} from './meeting.component';
import {Router, Routes} from '@angular/router';
import {CommonModule} from '@angular/common';
import {RouterTestingModule} from '@angular/router/testing';
import {TranslateLocalModule} from '../../../projects/shared/src/lib/translate';
describe('MeetingComponent', () => {
let sut: meetingComponent;
let fixture: ComponentFixture<MeetingComponent>;
// !! add router variable for later use !!
let router: Router;
const routes: Routes = [
{path: '', redirectTo: 'themen', pathMatch: 'full'},
{path: 'meeting', component: meetingComponent},
{path: '**', redirectTo: 'themen', pathMatch: 'full'}
];
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MeetingComponent ],
imports: [
CommonModule,
RouterTestingModule.withRoutes(routes),
TranslateLocalModule,
providers: [
]
}).compileComponents();
});
beforeEach(() => {
// !! get a handle on the router !!
router = TestBed.inject(Router);
fixture = TestBed.createComponent(MeetingComponent);
sut = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(sut).toBeTruthy();
});
it('should go on previous step', waitForAsync(() => {
// !! spy on the router !!
spyOn(router, 'navigate');
// !! I think this should be sut.goBack(); !!
sut.onPrevStep();
fixture.detectChanges();
// !! change expectation !!
expect(router.navigate).toHaveBeenCalledWith(['/themen']);
}));
});
在我的方法中,我有 this.router.navigate(['/themen']).then();这就是为什么当我应用@AliF50 解决方案时,它不起作用。如果我删除 .then() 测试解决方案工作正常。在这种情况下我可以做到,因为我在调用导航时不需要执行任何其他代码。
但如果您这样做,则必须提供承诺值。例如:
import {ComponentFixture, fakeAsync, inject, TestBed, waitForAsync} from '@angular/core/testing';
import {MeetingComponent} from './meeting.component';
import {Router, Routes} from '@angular/router';
import {CommonModule} from '@angular/common';
import {RouterTestingModule} from '@angular/router/testing';
import {TranslateLocalModule} from '../../../projects/shared/src/lib/translate';
describe('MeetingComponent', () => {
let sut: meetingComponent;
let fixture: ComponentFixture<MeetingComponent>;
let router: Router;
const routes: Routes = [
{path: '', redirectTo: 'themen', pathMatch: 'full'},
{path: 'meeting', component: meetingComponent},
{path: '**', redirectTo: 'themen', pathMatch: 'full'}
];
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MeetingComponent ],
imports: [
CommonModule,
RouterTestingModule.withRoutes(routes),
TranslateLocalModule,
providers: [
]
}).compileComponents();
!!The router spy must be declared here for me it did not work in the before each
// !! get a handle on the router !!
router = TestBed.inject(Router);
// !! spy on the router and return a Promise Value!!
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
});
beforeEach(() => {
fixture = TestBed.createComponent(MeetingComponent);
sut = fixture.componentInstance;
fixture.detectChanges();
router.initialNavigation();
});
it('should create', () => {
expect(sut).toBeTruthy();
});
it('should go on previous step', waitForAsync(() => {
sut.onPrevStep();
expect(router.navigate).toHaveBeenCalledWith(['/themen']);
}));
});
我想测试将我发送到特定页面的方法。我检查了几个示例,所有示例都按照我所做的相同方式完成,但我收到错误消息:
预期间谍导航已被调用: ['/主题'] 但它从未被调用过。 错误:预期的间谍导航已被调用: ['/主题'] 但它从未被调用过。
我的html代码是:
<button class="arrow-back-icon kf-tooltip-btn align-middle" id="backButton"
tabindex="0" name="ic_arrow-back_24" (click)="goBack()">
</button>
我组件中的方法是:
import {AfterViewChecked, ChangeDetectorRef, Component, OnInit} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';
import {SharingDataService} from '../services/sharing-data.service';
import {ActivatedRoute, Router} from '@angular/router';
import {BreakpointObserver} from '@angular/cdk/layout';
@Component({
selector: 'app-meeting',
templateUrl: './meeting.component.html',
styleUrls: ['./meeting.component.scss']
})
export class MeetingComponent implements OnInit, AfterViewChecked {
constructor(private readonly translate: TranslateService,
private readonly sharingDataService: SharingDataService,
private readonly router: Router,
private readonly activatedRoute: ActivatedRoute,
private readonly breakpointObserver: BreakpointObserver,
private readonly cd: ChangeDetectorRef) {
}
goBack(): void {
this.router.navigate(['/themen']).then();
}
}
测试是:
import {ComponentFixture, fakeAsync, inject, TestBed, waitForAsync} from '@angular/core/testing';
import {MeetingComponent} from './meeting.component';
import {Router, Routes} from '@angular/router';
import {CommonModule} from '@angular/common';
import {RouterTestingModule} from '@angular/router/testing';
import {TranslateLocalModule} from '../../../projects/shared/src/lib/translate';
describe('MeetingComponent', () => {
let sut: meetingComponent;
let fixture: ComponentFixture<MeetingComponent>;
const routes: Routes = [
{path: '', redirectTo: 'themen', pathMatch: 'full'},
{path: 'meeting', component: meetingComponent},
{path: '**', redirectTo: 'themen', pathMatch: 'full'}
];
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MeetingComponent ],
imports: [
CommonModule,
RouterTestingModule.withRoutes(routes),
TranslateLocalModule,
providers: [
]
}).compileComponents();
});
beforeEach(() => {fixture = TestBed.createComponent(MeetingComponent);
sut = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(sut).toBeTruthy();
});
it('should go on previous step', waitForAsync(() => {
const routerSpy = {
navigate: jasmine.createSpy('navigate')
};
sut.onPrevStep();
fixture.detectChanges();
expect (routerSpy.navigate).toHaveBeenCalledWith('/themen');
}));
});
谁能告诉我我做错了什么?
我也试过这个:
it('should navigates to previous step', fakeAsync(async () => {
spyOn(sut, 'onPrevStep').and.returnValue(await Promise.resolve());
const navigateSpy = spyOn(router, 'navigate');
sut.onPrevStep();
tick();
expect(sut.onPrevStep).toHaveBeenCalled();
expect(navigateSpy).toHaveBeenCalledWith(['/themen']);
}));
但是错误还是一样
谢谢!
是的,我认为您的 routerSpy
未与路由器相关联。
关注评论!!
试试这个:
import {ComponentFixture, fakeAsync, inject, TestBed, waitForAsync} from '@angular/core/testing';
import {MeetingComponent} from './meeting.component';
import {Router, Routes} from '@angular/router';
import {CommonModule} from '@angular/common';
import {RouterTestingModule} from '@angular/router/testing';
import {TranslateLocalModule} from '../../../projects/shared/src/lib/translate';
describe('MeetingComponent', () => {
let sut: meetingComponent;
let fixture: ComponentFixture<MeetingComponent>;
// !! add router variable for later use !!
let router: Router;
const routes: Routes = [
{path: '', redirectTo: 'themen', pathMatch: 'full'},
{path: 'meeting', component: meetingComponent},
{path: '**', redirectTo: 'themen', pathMatch: 'full'}
];
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MeetingComponent ],
imports: [
CommonModule,
RouterTestingModule.withRoutes(routes),
TranslateLocalModule,
providers: [
]
}).compileComponents();
});
beforeEach(() => {
// !! get a handle on the router !!
router = TestBed.inject(Router);
fixture = TestBed.createComponent(MeetingComponent);
sut = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(sut).toBeTruthy();
});
it('should go on previous step', waitForAsync(() => {
// !! spy on the router !!
spyOn(router, 'navigate');
// !! I think this should be sut.goBack(); !!
sut.onPrevStep();
fixture.detectChanges();
// !! change expectation !!
expect(router.navigate).toHaveBeenCalledWith(['/themen']);
}));
});
在我的方法中,我有 this.router.navigate(['/themen']).then();这就是为什么当我应用@AliF50 解决方案时,它不起作用。如果我删除 .then() 测试解决方案工作正常。在这种情况下我可以做到,因为我在调用导航时不需要执行任何其他代码。
但如果您这样做,则必须提供承诺值。例如:
import {ComponentFixture, fakeAsync, inject, TestBed, waitForAsync} from '@angular/core/testing';
import {MeetingComponent} from './meeting.component';
import {Router, Routes} from '@angular/router';
import {CommonModule} from '@angular/common';
import {RouterTestingModule} from '@angular/router/testing';
import {TranslateLocalModule} from '../../../projects/shared/src/lib/translate';
describe('MeetingComponent', () => {
let sut: meetingComponent;
let fixture: ComponentFixture<MeetingComponent>;
let router: Router;
const routes: Routes = [
{path: '', redirectTo: 'themen', pathMatch: 'full'},
{path: 'meeting', component: meetingComponent},
{path: '**', redirectTo: 'themen', pathMatch: 'full'}
];
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ MeetingComponent ],
imports: [
CommonModule,
RouterTestingModule.withRoutes(routes),
TranslateLocalModule,
providers: [
]
}).compileComponents();
!!The router spy must be declared here for me it did not work in the before each
// !! get a handle on the router !!
router = TestBed.inject(Router);
// !! spy on the router and return a Promise Value!!
spyOn(router, 'navigate').and.returnValue(Promise.resolve(true));
});
beforeEach(() => {
fixture = TestBed.createComponent(MeetingComponent);
sut = fixture.componentInstance;
fixture.detectChanges();
router.initialNavigation();
});
it('should create', () => {
expect(sut).toBeTruthy();
});
it('should go on previous step', waitForAsync(() => {
sut.onPrevStep();
expect(router.navigate).toHaveBeenCalledWith(['/themen']);
}));
});