Angular单元测试报错:无法读取undefined的'id'属性
问题:单元测试组件创建时报
TypeError: Cannot read properties of undefined (reading 'id') 我在实现商品更新功能时编写了updateItemData函数,从store中获取item,结合组件的this.name和this.price生成保留原id的updatedItem。项目运行时功能完全正常,但执行仅验证组件创建的单元测试用例时,出现TypeError: Cannot read properties of undefined (reading 'id')错误,虽然用例显示通过但存在报错,需要解决该问题。
相关代码
组件函数代码
public updateItemData(){ return this.store.select(itemSelector).subscribe(item => { this.updatedItem = { id: item.id, name: this.name, price: this.price } }) }
单元测试用例
it('should create', () => { expect(component).toBeTruthy(); });
错误原因
- 单元测试中未对store的
itemSelector返回值进行mock,导致store.select(itemSelector)发出的是undefined,订阅回调里访问item.id触发报错。 - 组件创建过程中(比如在
ngOnInit钩子中)自动调用了updateItemData函数,因此即使测试用例仅验证组件创建,也会触发该函数执行。
解决步骤
1. Mock Store并提供默认返回值
在测试模块的providers中配置mock Store,让select(itemSelector)返回一个包含有效id的item对象:
import { provideMockStore } from '@ngrx/store/testing'; import { itemSelector } from './path-to-your-selector'; beforeEach(async () => { await TestBed.configureTestingModule({ declarations: [YourComponent], providers: [ provideMockStore({ selectors: [ { selector: itemSelector, value: { id: 1, name: '测试商品', price: 99 } } ] }) ] }).compileComponents(); });
2. 增加空值判断避免报错
在订阅回调中先判断item是否存在,从根源上防止访问undefined的属性:
public updateItemData(){ return this.store.select(itemSelector).subscribe(item => { if (item) { this.updatedItem = { id: item.id, name: this.name, price: this.price } } }) }
3. 清理订阅避免内存泄漏
组件销毁时取消订阅,同时避免测试中的异步残留报错:
import { Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; private destroy$ = new Subject<void>(); public updateItemData(){ return this.store.select(itemSelector) .pipe(takeUntil(this.destroy$)) .subscribe(item => { if (item) { this.updatedItem = { id: item.id, name: this.name, price: this.price } } }) } ngOnDestroy() { this.destroy$.next(); this.destroy$.complete(); }
内容的提问来源于stack exchange,提问作者Curtis Lanz
相关产品推荐
相关产品推荐

