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

Angular单元测试遇undefined错误:无法读取banner_image_url属性

问题描述

已在component.ts中注入组件所需的服务与模型,但运行单元测试时出现错误:

TypeError: Cannot read properties of undefined (reading 'banner_image_url')

多次尝试解决均失败,不确定当前导入与声明是否正确,特附上相关代码寻求解决方法。

component.ts 代码

export class Component implements OnInit {
  subscriptions = new Subscription();
  filteredData: AddLandingPageResponse;
  faChevronLeft = faChevronLeft;

  constructor(
    public location: Location,
    private activatedRoute: ActivatedRoute,
    public store: Store<StoreState>
  ) {}
}

component.spec.ts 代码

let component: LandingDetailComponent;
let fixture: ComponentFixture<LandingDetailComponent>;
let translateService: TranslateService;
let mockStore: MockStore<StoreState['landing']>;

beforeEach(waitForAsync(() => {
  TestBed.configureTestingModule({
    declarations: [LandingDetailComponent, MockComponent(LoadingButtonComponent), SafeHtmlPipe],
    imports: [
      ModalModule.forRoot(),
      BrowserAnimationsModule,
      RouterTestingModule,
      TranslateModule.forRoot({
        loader: { provide: TranslateLoader, useClass: JsonTranslationLoader },
        compiler: {
          provide: TranslateCompiler,
          useClass: TranslateMessageFormatCompiler,
        },
      }),
      ToastrModule.forRoot({
        preventDuplicates: true,
        closeButton: true,
        progressBar: true,
      }),
    ],
    providers: [
      provideMockStore({ initialState: { ...mockInitialAppState } }),
      Location,
      TranslateService
    ],
  }).compileComponents();
}));

beforeEach(() => {
  fixture = TestBed.createComponent(LandingDetailComponent);
  fixture.detectChanges();
  component = fixture.componentInstance;
  translateService = TestBed.inject(TranslateService);
  landingService = TestBed.inject(LandingService);
  mockStore = TestBed.inject(MockStore);
  translateService.use('en');
});

describe('Component', () => {
  it('call the component', () => {
    expect(component).toBeTruthy();
  });
});
解决方法

这个错误的核心是filteredData未初始化,导致模板中尝试访问filteredData.banner_image_url时读取了undefined的属性,可从以下几个方向修复:

  • 初始化filteredData
    在组件类中给filteredData设置初始值,避免它处于undefined状态:

    // component.ts
    filteredData: AddLandingPageResponse = {} as AddLandingPageResponse;
    // 也可根据AddLandingPageResponse的结构提供更贴合的默认值
    // filteredData: AddLandingPageResponse = { banner_image_url: '' };
    
  • 模板中使用可选链操作符
    如果filteredData是从store异步获取的,在模板中访问属性时添加可选链,防止报错:

    <!-- 示例模板代码 -->
    <img [src]="filteredData?.banner_image_url" />
    
  • 完善MockStore初始状态
    若filteredData是从store的landing状态中获取的,需确保mock的初始状态包含对应数据:

    // 调整mockInitialAppState,补充landing相关数据
    const mockInitialAppState = {
      landing: {
        detail: { banner_image_url: 'test-url' }
        // 其他必要状态字段...
      }
      // 其他模块状态...
    };
    
  • 调整测试用例执行顺序
    当前测试先执行了fixture.detectChanges()(触发组件初始化和变更检测),之后才获取组件实例和mockStore。应先设置好mock数据,再执行变更检测:

    // 修改spec.ts中的beforeEach
    beforeEach(() => {
      fixture = TestBed.createComponent(LandingDetailComponent);
      component = fixture.componentInstance;
      translateService = TestBed.inject(TranslateService);
      landingService = TestBed.inject(LandingService);
      mockStore = TestBed.inject(MockStore);
      
      // 提前设置mockStore的状态数据
      mockStore.setState({
        ...mockInitialAppState,
        landing: { detail: { banner_image_url: 'test-url' } }
      });
      
      translateService.use('en');
      // 最后执行变更检测
      fixture.detectChanges();
    });
    

内容的提问来源于stack exchange,提问作者Manoj Kumar

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 17:35:23