Angular Router测试报错:无法读取未定义的属性'root'
解决Jasmine测试Router时出现"TypeError: Cannot read property 'root' of undefined"的问题
我来帮你搞定这个问题——你遇到的TypeError: Cannot read property 'root' of undefined,核心原因是你用jasmine.createSpyObj创建的Router Spy只模拟了navigate方法,但Angular的Router在组件初始化或模板渲染过程中,会访问root这类内部属性,而你的Spy对象里并没有提供这些属性,所以触发了错误。
下面给你两种可行的解决方案,推荐第一种更简洁可靠的方式:
方案一:使用Angular官方的RouterTestingModule
Angular专门提供了RouterTestingModule用于路由相关组件的测试,它会自动提供一个完整的模拟Router环境,包含所有必要的属性和方法,不需要手动创建Spy对象。
修改后的测试代码如下:
describe('Error404Component', () => { let component: Error404Component; let fixture: ComponentFixture<Error404Component>; let router: Router; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [RouterTestingModule.withRoutes([])], // 导入测试用路由模块 declarations: [Error404Component] // 直接声明组件,无需导入整个AppModule(避免冗余依赖) }).compileComponents(); })); beforeEach(() => { router = TestBed.inject(Router); // 获取模拟的Router实例 spyOn(router, 'navigate'); // 对navigate方法打桩 fixture = TestBed.createComponent(Error404Component); component = fixture.componentInstance; fixture.autoDetectChanges(); }); fit('should navigate to home when button is clicked', fakeAsync(() => { const buttons = fixture.debugElement.queryAll(By.css('.button_link')); expect(buttons.length).toBeGreaterThan(0); // 更精准的断言,确保按钮存在 const homeButton = buttons[0]; homeButton.nativeElement.click(); fixture.detectChanges(); tick(); // 直接断言navigate方法的调用参数 expect(router.navigate).toHaveBeenCalledWith([HOME_PATH]); })); });
方案二:手动给Spy对象补充root属性
如果你坚持要手动创建SpyObj,可以给它添加root属性(以及其他可能需要的属性),不过这种方式容易遗漏其他依赖属性,不推荐:
// 创建包含root属性的SpyObj const routerSpy = jasmine.createSpyObj( 'Router', ['navigate'], { root: jasmine.createSpyObj('RouterRoot', ['']) } );
为什么方案一更优?
RouterTestingModule会模拟整个Router的运行环境,包括路由状态、导航事件等,比手动创建SpyObj更贴近真实场景,也避免了手动模拟时遗漏属性或方法的问题,同时代码更简洁易维护。
内容的提问来源于stack exchange,提问作者José Soler
相关产品推荐
相关产品推荐

