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

Angular 20基于Jasmine的单元测试报错:TypeError: Cannot read properties of undefined (reading 'root') 求解决方案

解决Angular Jasmine测试中"Cannot read properties of undefined (reading 'root')"的问题

这个错误的核心原因是你在测试模块中导入了完整的AppRoutingModule,测试环境下Angular无法正确初始化路由系统的根节点;同时你的App组件模板包含<router-outlet>,真实路由模块会触发匹配路由组件(比如Login组件)的加载,引入额外依赖问题。

下面是具体的解决方案:

1. 用RouterTestingModule替代AppRoutingModule

Angular专门提供了RouterTestingModule用于路由相关单元测试,它会模拟路由核心功能,不会加载真实路由配置,完美适配测试场景。修改你的测试代码如下:

import { TestBed } from '@angular/core/testing';
import { App } from './app';
import { AuthService } from './services/auth-service';
import { RouterTestingModule } from '@angular/router/testing'; // 导入测试用路由模块
import { MatToolbarModule } from '@angular/material/toolbar';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
// 移除AppRoutingModule的导入

describe('App', () => {
  let authServiceSpy: jasmine.SpyObj<AuthService>;

  beforeEach(async () => {
    authServiceSpy = jasmine.createSpyObj('AuthService', ['isLoggedIn', 'logout']);
    authServiceSpy.isLoggedIn.and.returnValue(false);

    // 模拟localStorage,避免依赖浏览器环境
    spyOn(localStorage, 'getItem').and.returnValue('test-user');

    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule, // 替换为测试用路由模块
        MatToolbarModule,
        MatIconModule,
        MatButtonModule
      ],
      declarations: [App],
      providers: [
        { provide: AuthService, useValue: authServiceSpy }
        // RouterTestingModule已经提供了Router的mock,无需手动创建routerSpy
      ]
    }).compileComponents();
  });

  it('should create the app', () => {
    const fixture = TestBed.createComponent(App);
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

  // 可选:验证logout的路由跳转行为
  it('should navigate to login-form after logout', () => {
    const fixture = TestBed.createComponent(App);
    const app = fixture.componentInstance;
    const router = TestBed.inject(Router);
    const navigateSpy = spyOn(router, 'navigate');

    app.logout();
    expect(navigateSpy).toHaveBeenCalledWith(['/login-form']);
    expect(authServiceSpy.logout).toHaveBeenCalled();
  });
});

2. 关键修复点说明

  • 替换路由模块:RouterTestingModule会自动配置测试所需的路由依赖,支持<router-outlet>渲染,同时不会加载真实路由配置,避免了"root"属性未定义的错误。
  • 模拟localStorage:组件直接调用localStorage.getItem,测试时模拟该API可以避免依赖浏览器环境,让测试更稳定。
  • 移除多余的Router Spy:RouterTestingModule已经提供了Mock Router实例,无需手动创建routerSpy,如果需要验证路由行为,直接从TestBed获取实例即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 06:40:30