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
相关产品推荐
相关产品推荐

