Angular单元测试报错:TypeError: 无法读取undefined的'state'属性
Angular单元测试报错:TypeError: Cannot read properties of undefined (reading 'state')
运行npm test时触发该错误,核心原因有两点:
CarePlanService在初始化tokenResponse属性时,直接调用了FHIRService的getTokenResponse方法FHIRService的getTokenResponse方法依赖未初始化的fhirClient对象,同时单元测试中Mock的FHIRService未设置getTokenResponse的返回值
相关代码片段
service.ts 文件
constructor(private http: HttpClient, private fhirServcie: FHIRService) { } tokenResponse:any = this.fhirServcie.getTokenResponse(); getCarePlanDetails(): Observable<any> { ... }
FHIR.service.ts 文件
public fhirClient!: Client; setFhirClient(client: Client) { this.fhirClient = client } getTokenResponse() { return this.fhirClient.state.tokenResponse; }
service.spec.ts 文件
describe('CarePlanService', () => { let service: CarePlanService; let httpTestingController: HttpTestingController; let mockFhirService: jasmine.SpyObj<FHIRService>; beforeEach(() => { TestBed.configureTestingModule({ imports: [HttpClientTestingModule, RouterTestingModule], providers: [ { provider: FHIRService, useValue: jasmine.createSpyObj('FHIRService', ['getTokenResponse']) }] }); httpTestingController = TestBed.get(HttpTestingController); service = TestBed.get(CarePlanService); mockFhirService = TestBed.get(FHIRService); }); afterEach(() => { httpTestingController.verify(); }); it('should be created', () => { expect(service).toBeTruthy(); }); });
示例Client对象
{ "state":{ "tokenResponse": { "access_token": "fsdjfhsjkfk" } }}
修复方案
1. 给Mock的getTokenResponse设置返回值
在单元测试的beforeEach中,给Mock对象指定返回值,避免调用时返回undefined:
beforeEach(() => { // ... 原有初始化代码 mockFhirService = TestBed.get(FHIRService); // 模拟返回预期的tokenResponse结构 mockFhirService.getTokenResponse.and.returnValue({ access_token: 'mock-token' }); });
2. 优化FHIRService的空值判断
修改getTokenResponse方法,增加空值校验,避免实际运行时因fhirClient未初始化报错:
getTokenResponse() { // 使用可选链操作符,避免空值访问报错 return this.fhirClient?.state?.tokenResponse || null; }
3. 延迟tokenResponse的初始化时机
不要在类属性中直接调用方法初始化,改为在fhirClient已被设置后再赋值:
tokenResponse: any; constructor(private http: HttpClient, private fhirServcie: FHIRService) { } // 比如在调用setFhirClient之后,通过初始化方法赋值 initToken() { this.tokenResponse = this.fhirServcie.getTokenResponse(); }
内容的提问来源于stack exchange,提问作者Ashu J
相关产品推荐
相关产品推荐

