Angular运行ng test时读取dateOfLeaving等属性报undefined错误如何解决
问题根因
- 组件
ngOnInit生命周期的执行时机早于你在测试用例中给component.emp赋值的时机:调用TestBed.createComponent()时就会触发组件初始化,此时ngOnInit已经执行完成,你后续给component.emp赋值完全不会生效。 - 就算你提前赋值了
component.emp也没用,ngOnInit第一行代码是this.emp = this.employeeService.selectedEmployee,会直接把组件的emp变量覆盖为服务中的selectedEmployee值,而你测试时注入的EmployeeService实例里selectedEmployee默认是未赋值的undefined,访问undefined.dateOfLeaving就会直接抛出你遇到的报错。
解决方案
方案1:调整测试用例赋值顺序,提前初始化服务中的选中员工数据
修改view-employee.component.spec.ts的第二个beforeEach逻辑:
beforeEach(() => { // 先从测试模块中拿到注入的EmployeeService实例 const employeeService = TestBed.inject(EmployeeService); // 提前给服务的selectedEmployee赋值,这样组件ngOnInit拿到的就是正确的对象 employeeService.selectedEmployee = new Employee(); employeeService.selectedEmployee.id =1; employeeService.selectedEmployee.dateOfLeaving ="Today"; fixture = TestBed.createComponent(ViewEmployeeComponent); component = fixture.debugElement.componentInstance; fixture.detectChanges(); });
同时把should create用例里注释的断言打开,否则测试会永远显示通过:
it('should create', () => { expect(component).toBeTruthy(); });
方案2:给组件增加防御性编码,避免运行时/测试时的空值报错
修改view-employee.component.ts的ngOnInit逻辑,加空值判断:
ngOnInit() { this.emp = this.employeeService.selectedEmployee; // 先判断emp是否存在再访问属性 if(this.emp?.dateOfLeaving == null) { // 如果emp存在才赋值,不存在可以先初始化一个空Employee对象 this.emp = this.emp || new Employee(); this.emp.dateOfLeaving = ''; } // 剩下的原有逻辑不变 }
方案3(推荐):mock依赖的服务,避免测试耦合真实服务逻辑
单元测试只需要验证组件本身的逻辑,不需要依赖真实的EmployeeService和CommonService,可以在测试模块中直接提供mock实现,测试更稳定也不需要处理HTTP请求依赖:
// 在spec文件顶部先定义mock服务 class MockEmployeeService { selectedEmployee = Object.assign(new Employee(), { id: 1, dateOfLeaving: 'Today' }); updateEmployee = jasmine.createSpy('updateEmployee').and.returnValue(of({status: 200, message: 'success'})); } class MockCommonService { getWorkLocations = jasmine.createSpy('getWorkLocations').and.returnValue(of(['北京', '上海', '广州'])); } // 然后修改TestBed的providers配置 providers: [ {provide: EmployeeService, useClass: MockEmployeeService}, {provide: CommonService, useClass: MockCommonService} ]
这样完全不需要依赖真实服务的实现,也不用处理HTTP模块的相关问题,测试执行速度更快也更稳定。
内容的提问来源于stack exchange,提问作者Vineel Pellella
相关产品推荐
相关产品推荐

