Angular Karma/Jasmine单元测试报错:无法读取undefined的imageUrl属性
Angular单元测试报错排查:Cannot read properties of undefined reading imageUrl
问题背景
三个组件单元测试均失败,报错信息为Cannot read properties of undefined reading imageUrl,错误源自组件模板。尝试在TestBed中配置相关属性但无效,组件无法正常创建,目前已注释部分测试,附相关代码片段寻求排查方向与解决方案。
相关代码片段
模型文件 product.ts
export class Product { _id:string; name: string; size: string; description: string; price: number; imageUrl: string; static price: Product; constructor(_id:string, name: string, description="", size:string, price=0, imageUrl=""){ this._id=_id; this.name = name; this.description = description; this.price= price; this.size= size; this.imageUrl = imageUrl; } }
组件模板 product-item.component.html
<img class=" img-fluid shacker" [src]="productItem.imageUrl" alt="Clothing" />
测试文件 product-item.component.spec.ts
import { ComponentFixture, TestBed, async } from '@angular/core/testing'; import { WishlistItemService } from '@app/services/wishlist-item.service'; import { CartService } from '@app/services/cart.service'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { ProductItemComponent } from './product-item.component'; import { RouterTestingModule } from '@angular/router/testing'; import { AlertComponent } from '@app/_components'; import { Product } from '@app/models/product'; const FAKE_PRODUCTS:Product[] = [ { "_id": "0001", "name": "Black One Piece", "size": "M", "description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.", "imageUrl": "http://localhost:4200/assets/BlacknwhiteOne.png", "price": 199 }, { "_id": "00002", "name": "Overalls", "size": "M", "description": "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.", "imageUrl": "http://localhost:4200/assets/overalls.png", "price": 250 } ] const okResponse = new Response(JSON.stringify(FAKE_PRODUCTS), { status: 200, statusText: 'OK' }); describe('ProductItemComponent', () => { let component: ProductItemComponent; let fixture: ComponentFixture<ProductItemComponent>; beforeEach(async () => { const wishlistitemServiceSpy = jasmine.createSpyObj<WishlistItemService>(['addProductItemToWishlistItem']); const cartServiceSpy = jasmine.createSpyObj<CartService>(['addAllproducts']); await TestBed.configureTestingModule({ declarations: [ ProductItemComponent, AlertComponent ], imports:[HttpClientTestingModule, RouterTestingModule], providers:[ { WishlistItemService, useValue: wishlistitemServiceSpy, CartService, uses: cartServiceSpy } ] }) .compileComponents(); }); beforeEach(() => { fixture = TestBed.createComponent(ProductItemComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { component.imageUrl //this is where I'm having trouble it needs to be mentioned not sure how expect(component).toBeTruthy(); }); });
组件文件 product-item.component.ts 片段
export class ProductItemComponent implements OnInit { [x: string]: any; form!: UntypedFormGroup; submitted=false; sizeBy!: string; Valuesize!: string; size!: string; imageUrl!: string //products is my database collection //Products is my model/interface for db products:Products[] = []; cartItems: CartItem[] = []; @Input() cartItem!: CartItem; @Input() productItem!: Product; ngOnInit() { this.form = this.formBuilder.group({ sizeBy: ['', Validators.required] }); } }
问题排查与解决方案
核心问题分析
- 输入属性未初始化:组件模板直接访问
productItem.imageUrl,但测试中创建组件时未给@Input() productItem赋值,导致productItem为undefined,触发报错。 - TestBed配置错误:
providers数组中的服务配置写法错误,多个服务不能放在同一个对象内,且CartService的配置关键字写错为uses,正确应为useValue。
具体修复步骤
初始化输入属性
在测试的第二个beforeEach中,调用fixture.detectChanges()之前,给productItem赋值:beforeEach(() => { fixture = TestBed.createComponent(ProductItemComponent); component = fixture.componentInstance; // 给输入属性赋值 component.productItem = FAKE_PRODUCTS[0]; fixture.detectChanges(); });修正TestBed服务配置
将providers中的服务配置拆分为独立对象,修正关键字错误:providers:[ { provide: WishlistItemService, useValue: wishlistitemServiceSpy }, { provide: CartService, useValue: cartServiceSpy } ]清理无效代码
删除测试用例中无效的component.imageUrl代码,修正后的测试用例:it('should create', () => { expect(component).toBeTruthy(); });
完成以上修改后,组件能正常获取productItem数据,模板渲染不会再触发undefined报错,单元测试可正常执行。
内容的提问来源于stack exchange,提问作者user2280852
相关产品推荐
相关产品推荐

