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
相关产品推荐
相关产品推荐

