Angular 9中如何测试带有relativeTo参数的路由?
如何正确测试Angular 9中带有
relativeTo的路由? 问题背景
组件方法代码
initiateDetailsView(detailsData) { this.router.navigate(['./personnel-details'], { relativeTo: this.activatedRoute, }); }
初始测试用例
it('should navigate to details page', () => { const routerNavigateSpy = spyOn(router, 'navigate'); component.initiateDetailsView({}); fixture.detectChanges(); expect(routerNavigateSpy).toHaveBeenCalledWith([ './personnel-details', { relativeTo: 'clinic-admin/scok-personnel' }, ]); });
初始错误信息
Expected spy navigate to have been called with: [ [ './personnel-details', Object({ relativeTo: 'clinic-admin/scok-personnel' }) ] ] but actual calls were: [ [ './personnel-details' ], Object({ relativeTo: Route(url:'', path:'') }) ].
更新后的测试代码及新错误
更新后的测试代码:
fdescribe('ListPersonnelComponent', () => { let component: ListPersonnelComponent; let fixture: ComponentFixture<ListPersonnelComponent>; let location: Location; let activatedRoute:ActivatedRoute; let router; const routes = [ { path: 'personnel-details', component: PersonnelDetailsComponent, relativeTo: activatedRoute, }, ]; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule.withRoutes(routes), SharedModule, BrowserAnimationsModule, HttpClientModule, ], declarations: [ListPersonnelComponent], providers: [PersonnelDataService], }).compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(ListPersonnelComponent); component = fixture.componentInstance; router = TestBed.inject(Router); fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); it('should navigate to details page', () => { const routerNavigateSpy = spyOn(router, 'navigate'); component.initiateDetailsView({}); fixture.detectChanges(); expect(routerNavigateSpy).toHaveBeenCalledWith([ './personnel-details', { relativeTo: activatedRoute }, ]); }); });
出现新错误:变量“activatedRoute”在赋值前被使用.ts(2454)
解决方案
1. 模拟并注入ActivatedRoute实例
组件中relativeTo传入的是ActivatedRoute实例而非字符串,测试时需要创建模拟的ActivatedRoute对象并注入测试模块:
// 在测试块顶部声明模拟对象 let activatedRoute: SpyObj<ActivatedRoute>; // 在async beforeEach中初始化模拟对象并配置到TestBed beforeEach(async(() => { // 创建包含必要属性的ActivatedRoute模拟(根据组件实际使用的属性调整) activatedRoute = jasmine.createSpyObj('ActivatedRoute', [], { snapshot: { url: [], path: '' }, parent: null }); TestBed.configureTestingModule({ imports: [ RouterTestingModule.withRoutes(routes), SharedModule, BrowserAnimationsModule, HttpClientModule, ], declarations: [ListPersonnelComponent], providers: [ PersonnelDataService, { provide: ActivatedRoute, useValue: activatedRoute } // 注入模拟对象 ], }).compileComponents(); }));
2. 修正路由配置
路由定义中不存在relativeTo属性,移除routes数组里的该配置项:
const routes = [ { path: 'personnel-details', component: PersonnelDetailsComponent }, ];
3. 修正测试断言
断言时使用模拟的activatedRoute实例匹配组件调用navigate的参数:
it('should navigate to details page with correct relativeTo', () => { const routerNavigateSpy = spyOn(router, 'navigate'); component.initiateDetailsView({}); // 注意参数结构:第一个是路径数组,第二个是配置对象 expect(routerNavigateSpy).toHaveBeenCalledWith( ['./personnel-details'], { relativeTo: activatedRoute } ); });
错误原因说明
- 初始错误:断言中用字符串作为
relativeTo的值,但组件实际传入的是ActivatedRoute实例,导致匹配失败。 - 更新后的错误:全局定义的
routes数组引用了未赋值的activatedRoute变量,activatedRoute在beforeEach中才会初始化,全局作用域下变量未赋值就被使用。
内容的提问来源于stack exchange,提问作者3gwebtrain
相关产品推荐
相关产品推荐

