You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular单元测试模拟router.events.subscribe报错求助

Angular单元测试模拟router.events.subscribe报错解决

问题场景

在Angular单元测试中手动模拟Router对象的events时,触发错误:TypeError: Cannot read properties of undefined (reading 'root'),相关代码如下:

组件TS代码

ngOnInit(): void {
    this.router.events.subscribe(event => {
        this.splitRoutes();
    });
}

private splitRoutes() {
    const routes = this.router.url.toString().split('/');
    // 其他业务逻辑
}

测试spec.ts代码

beforeEach(async () => {
    await TestBed.configureTestingModule({
        imports: [],
        providers: [{
            provide: Router,
            useValue: {
                url: '/non-pdp/phases/8',
                events: of(
                    new NavigationEnd(0, 'http://localhost:4200/#/non-pdp/phases/8', 'http://localhost:4200/#/non-pdp/phases/8')),
                navigate: jasmine.createSpy('navigate')
            }],
        })
        .compileComponents();
});

错误原因

手动模拟的Router对象缺少Angular内部处理路由事件时依赖的属性(比如routerState.root),虽然你的组件代码没有直接调用这些属性,但Angular在订阅router.events的内部逻辑中会访问它们,导致未定义报错。

解决方案

方案一:完善Router模拟对象

给模拟的Router补充routerState和root属性,满足Angular内部逻辑的访问需求:

beforeEach(async () => {
    await TestBed.configureTestingModule({
        imports: [],
        providers: [{
            provide: Router,
            useValue: {
                url: '/non-pdp/phases/8',
                events: of(
                    new NavigationEnd(0, 'http://localhost:4200/#/non-pdp/phases/8', 'http://localhost:4200/#/non-pdp/phases/8')),
                navigate: jasmine.createSpy('navigate'),
                // 添加缺失的路由状态属性
                routerState: {
                    root: {}
                }
            }],
        })
        .compileComponents();
});

方案二:使用RouterTestingModule(推荐)

Angular官方提供的RouterTestingModule会自动配置完整的Router测试环境,避免手动模拟遗漏属性的问题:

import { RouterTestingModule } from '@angular/router/testing';

beforeEach(async () => {
    await TestBed.configureTestingModule({
        // 导入RouterTestingModule,可根据需求配置测试路由
        imports: [RouterTestingModule.withRoutes([])],
        // 无需手动提供Router,模块会自动注入测试用实例
        providers: [],
    })
    .compileComponents();

    // 获取Router实例并自定义url和events
    const router = TestBed.inject(Router);
    spyOnProperty(router, 'url').and.returnValue('/non-pdp/phases/8');
    router.events = of(
        new NavigationEnd(0, 'http://localhost:4200/#/non-pdp/phases/8', 'http://localhost:4200/#/non-pdp/phases/8')
    );
});

使用RouterTestingModule的优势在于它会模拟完整的Router上下文,包括路由状态、导航行为等,后续如果组件用到更多Router的属性或方法,无需手动补充模拟,稳定性更强。

内容的提问来源于stack exchange,提问作者denisiulian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 08:15:44