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

TypeError: Cannot read properties of undefined (reading 'id') 测试API调用报错求助

问题排查与解决方案

错误触发根因

这个TypeError: Cannot read properties of undefined (reading 'id')报错是代码尝试读取undefined值的id属性导致的,结合你的代码有两个明确的触发场景:

1. 单测场景触发

你的单测代码仅对api.send做了调用监听,没有配置符合业务逻辑的模拟返回值:

  • 首先如果component.addItem方法没有正确将传入的item赋值给组件的this.item属性,第一次调用api.send时读取this.item['id']就会直接报错
  • 其次即使this.item初始值正常,spyOn(api, 'send')默认会替换原方法且返回undefined,若你没有手动配置spy返回Promise,业务代码调用api.send后尝试调用.then()会先触发undefined调用then的错误;即使你配置了返回空Promise,但没有模拟返回的data数组,第一个.then里拿到的resEsp.data[0]就是undefined,赋值给this.item后,第二次调用api.send时读取this.item.id就会触发你遇到的报错

2. 生产运行时触发

业务代码没有对接口返回值做非空校验:
调用第一个ES语言的接口后,直接取resEsp['data'][0]赋值给this.item,如果接口返回的data是空数组、或者接口返回结构不符合预期,resEsp['data'][0]就是undefined,后续读取this.item.id就会触发报错。

修复方案

1. 单测代码修复

给spy配置模拟返回值,同时处理异步断言:

it('should call api.send', async () => {
    // 模拟api.send返回符合业务预期的结构
    let spy1 = spyOn(api, 'send').and.returnValue(Promise.resolve({
        data: [{
            id: 1,
            name: 'test'
            // 补充其他业务需要的字段
        }]
    }));
    let item = {
        id: 1,
        name: 'test',
    }

    component.addItem(item);
    component.itemToForm();
    // 等待异步逻辑执行完成再做断言
    await spy1.calls.mostRecent().returnValue;

    expect(spy1).toHaveBeenCalled();
});

修复前先确认component.addItem方法逻辑正常,确实会将传入的item赋值给组件的this.item属性。

2. 业务代码健壮性优化

增加非空判断,避免接口返回异常时直接报错,同时调整Promise写法避免嵌套回调地狱:

itemToForm = () => {
    // 先判断初始item是否存在合法id
    if (!this.item?.id) return;
    // 如果运行环境不支持可选链,替换为 if (!this.item || !this.item.id) return
    this.api.send(this.component, 'get',
        { lang: 'ES', filter: { id: this.item['id'] } }
    ).then(resEsp => {
        // 校验返回的data数组是否有值
        if (!resEsp?.data?.length) return;
        this.item = resEsp['data'][0];
        return this.api.send(this.component, 'get',
            { lang: 'EN', filter: { id: this.item['id'] } }
        );
    }).then(res => {
        if (!res?.data?.length) {
            // 英文接口无返回时也可正常执行基础setForm逻辑
            if (this.item) this.setForm();
            return;
        }
        let itemEng = res['data'][0];
        let fields = this.formDef.map(register => register.filter(
            field => field['register_table'].indexOf('traduction') !== -1
        ).map(
            field => field['field_name'])
        ).filter(register => register.length);

        fields = fields.length ? fields[0] : [];

        if (itemEng) {
            this.item = Object.keys(itemEng).reduce((obj, key) => {
                obj[key] = this.item[key];
                if (fields.indexOf(key) !== -1) {
                    obj[key + '_eng'] = itemEng[key];
                }
                return obj;
            }, {});
        }

        if (this.item) {
            this.setForm();
        }
    }).catch(err => {
        // 增加异常捕获,避免接口报错导致页面逻辑阻塞
        console.error('获取多语言数据失败', err);
    })
}

内容的提问来源于stack exchange,提问作者David Angarita

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 14:15:03