You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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();
});

错误原因

  1. 单元测试中未对store的itemSelector返回值进行mock,导致store.select(itemSelector)发出的是undefined,订阅回调里访问item.id触发报错。
  2. 组件创建过程中(比如在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 14:30:42