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

Angular单元测试遇Cannot read property 'navigate' of undefined错误及疑问

解决Angular单元测试中“Cannot read property 'navigate' of undefined”的问题

这个报错的根源很明确:你的choix方法内部肯定调用了Router的navigate方法,但在单元测试的环境里,Router实例没有被正确初始化或者注入,导致它是undefined,调用navigate自然就抛出错误了。

下面给你两种最常用的解决办法:

方法一:使用RouterTestingModule快速配置模拟路由

Angular官方提供了RouterTestingModule,它能帮你快速搭建一个适合测试的模拟路由环境,不用手动mock太多东西:

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

beforeEach(async(() => {
  TestBed.configureTestingModule({
    imports: [RouterTestingModule], // 导入这个模块,会自动提供模拟的Router实例
    declarations: [YourComponent], // 替换成你的组件类名
    providers: [AuthService]
  }).compileComponents();
}));

方法二:手动创建Router的Spy对象(更灵活,适合需要验证导航行为的场景)

如果需要验证navigate方法是否被调用、调用参数是什么,手动创建spy对象会更方便:

import { Router } from '@angular/router';

// 先声明一个spy对象变量
let routerSpy: jasmine.SpyObj<Router>;

beforeEach(async(() => {
  // 创建Router的spy,只模拟我们需要用到的navigate方法
  routerSpy = jasmine.createSpyObj('Router', ['navigate']);

  TestBed.configureTestingModule({
    declarations: [YourComponent],
    providers: [
      AuthService,
      { provide: Router, useValue: routerSpy } // 把spy对象注入到测试环境中
    ]
  }).compileComponents();
}));

用这种方式的话,你还能在测试里加个断言,验证导航是否按预期触发:

it('点击确定按钮时应调用服务器以发送验证码选项并执行导航', () => {
  import { EMPTY } from 'rxjs';
  const authSpy = spyOn(authService, 'choixReceptionCode').and.returnValue(EMPTY); // Angular 6+推荐用EMPTY替代Observable.empty()
  component.choix('mail');
  
  // 验证服务方法被调用
  expect(authSpy).toHaveBeenCalledWith('mail');
  // 验证导航方法被调用,这里替换成你实际的路由路径
  expect(routerSpy.navigate).toHaveBeenCalledWith(['/your-target-route']);
});

最后补充个小提示:如果你用的是较新版本的Angular,建议用EMPTY(从rxjs导入)替代Observable.empty(),后者已经被标记为废弃啦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:33:53