Angular 4单元测试注入Router模块报错:ReferenceError: Router未定义
解决Angular 4单元测试中inject注入Router时的ReferenceError问题
我来帮你排查这个问题,从你的代码和堆栈信息来看,主要有几个明显的问题导致了这个错误,咱们一步步来修复:
问题分析
- 未定义的
getVendorsDataStub:你在TestBed的providers里配置了DriverService使用getVendorsDataStub,但这个变量根本没有定义,这会直接导致TestBed初始化失败,破坏整个依赖注入环境,进而让inject无法正确获取Router实例。 - inject回调的依赖解析问题:虽然你导入了Router,但如果TestBed的配置失败,inject函数无法正确解析依赖,就会抛出类似的未定义错误。另外你在it块里才初始化fixture和component,也不符合单元测试的最佳实践。
- 多余的语法闭合符:你的describe块最后多了一个
),这会导致语法错误,影响测试代码的正常执行。
修正后的测试代码
import { TestBed, async, inject, fakeAsync, tick, ComponentFixture, getTestBed } from '@angular/core/testing'; import { RouterTestingModule } from "@angular/router/testing"; import { Router } from "@angular/router"; import { Location } from "@angular/common"; import { DriversModule } from '../../drivers.module'; import { DriverAddComponent } from './driver.add.component'; import { routes, routing } from '../../drivers.routing'; import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; import { By } from '@angular/platform-browser'; import { Observable } from 'rxjs/Observable'; import { DriverService } from '../../services/driver.service'; // 先定义DriverService的Stub类,替换未定义的getVendorsDataStub class DriverServiceStub { // 根据DriverService的实际方法补充Stub实现 // 示例:如果有获取供应商的方法 // getVendors() { // return Observable.of([]); // } } describe('Add driver Component', () => { let component: DriverAddComponent; let fixture: ComponentFixture<DriverAddComponent>; let routerMock; let router: Router; let location: Location; beforeEach(async(() => { routerMock = { navigate: jasmine.createSpy('navigate') }; TestBed.configureTestingModule({ imports: [ DriversModule, RouterTestingModule.withRoutes(routes) ], providers: [ { provide: Router, useValue: routerMock }, { provide: DriverService, useClass: DriverServiceStub } // 使用定义好的Stub类 ], schemas: [NO_ERRORS_SCHEMA] }).compileComponents(); })); // 在beforeEach中统一初始化组件和依赖,避免重复代码 beforeEach(() => { fixture = TestBed.createComponent(DriverAddComponent); component = fixture.componentInstance; router = TestBed.get(Router); // 直接从TestBed获取Router实例,无需inject location = TestBed.get(Location); }); it('should navigate to the add a new driver page', () => { component.goBack(); expect(router.navigate).toHaveBeenCalledWith(['/addDriver']); // 额外:如果想验证实际导航路径,可使用fakeAsync配合Location测试 // fakeAsync(() => { // component.goBack(); // tick(); // expect(location.path()).toBe('/addDriver'); // }) }); });
关键修改点说明
- 补充DriverServiceStub:必须提供有效的DriverService替代类,否则TestBed无法完成初始化,依赖注入系统会直接崩溃,你需要根据实际业务方法补充Stub的具体实现。
- 提前初始化组件实例:在beforeEach里完成组件和依赖的初始化,确保每个测试用例都能拿到干净的组件实例,同时减少重复代码。
- 改用TestBed.get获取依赖:相比inject函数,直接通过
TestBed.get(Router)获取实例更直观,也能避免inject相关的作用域问题。 - 修复语法错误:去掉了describe块末尾多余的闭合括号,确保代码语法完全正确。
额外建议
如果你还是想使用inject函数,一定要确保TestBed配置完全正确,且代码没有语法错误。另外Angular 4的测试推荐使用TestBed.get来获取依赖,这是更简洁且不易出错的方式。
内容的提问来源于stack exchange,提问作者Harish98
相关产品推荐
相关产品推荐

