Angular单元测试报错Cannot read property 'preferences' of undefined如何解决
问题根因
你的代码存在4个核心问题,直接导致报错:
- 组件
ngOnInit生命周期中直接读取this.data.preferences,但你没有给私有属性data赋值,且测试代码中fixture.detectChanges()执行时机过早,触发ngOnInit时this.data为undefined,访问属性直接抛出错误。 - 测试模块配置的
declarations数组中填写的组件名是PreferencesComponent,和实际组件类名PreferComponent拼写不一致,会导致组件初始化失败。 - 你在测试中直接给
component.preferences/maxCols/selectedPref赋值是无效操作:ngOnInit执行时会用this.data里的属性直接覆盖这些值。 - 组件代码中调用了
checkPreferences()方法,但你没有给出该方法的实现,运行时会额外抛出方法不存在的错误。
修复方案
1. 先修改组件代码
给data属性添加@Input()装饰器(符合Angular父组件传值的规范),同时补全checkPreferences方法的逻辑:
import { Input } from '@angular/core'; // 顶部引入Input装饰器 export class PreferComponent implements OnInit { @Output() updatePreferences = new EventEmitter<any>(); @ViewChild('settingModal', { static: true }) settingModal: any; @Input() data: any; // 改成Input输入属性 preferences = []; maxCols: number; selectedPref: number; constructor() { } ngOnInit(): void { this.preferences = JSON.parse(JSON.stringify(this.data.preferences)); this.maxCols = this.data.maxCols; this.selectedPref = this.data.selectedPref; this.checkPreferences(); } // 补全该方法逻辑,可根据实际业务调整 checkPreferences() { // 你的业务逻辑 } setPreferences(col, val) { if (val) { col.isPreferredColumn = true; this.selectedPref++; } else { col.isPreferredColumn = false; this.selectedPref--; } this.checkPreferences(); } }
2. 再修改测试代码
调整属性赋值和detectChanges的执行顺序,修正组件拼写错误,删除冗余的手动调用ngOnInit代码:
fdescribe('PreferComponent', () => { let component: PreferComponent; let fixture: ComponentFixture<PreferComponent>; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [PreferComponent], // 修正组件名拼写 schemas: [CUSTOM_ELEMENTS_SCHEMA] }) .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(PreferComponent); component = fixture.componentInstance; // 先给Input属性data赋值,再触发生命周期 const data1 = { preferences: [1, 2, 4], maxCols: 5, selectedPref: 7 }; component.data = data1; // 第一次detectChanges会自动触发ngOnInit,不需要手动调用 fixture.detectChanges(); expect(component.preferences).toEqual([1, 2, 4]); }); it('should create', () => { expect(component).toBeTruthy(); }); });
修改完成后重新运行测试即可解决报错。
内容的提问来源于stack exchange,提问作者Nitin
相关产品推荐
相关产品推荐

