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

Angular 15.1升级后含静态数据的组件单元测试失败求助

Angular 15.1升级后单元测试静态属性读取失败问题解决

问题描述

Angular 15.0项目升级至15.1后,执行yarn test-coverage触发单元测试失败,ZoomControlComponent组件报以下错误:

Uncaught TypeError: Cannot read properties of undefined (reading 'PredefinedZoomEnumMapList')

组件中定义了静态属性PredefinedZoomEnumMapList,并通过类名直接引用它来初始化另一个静态属性PredefinedZoomEnumLabelList。

组件代码片段

@Component({
  selector: 'mad-zoom-control',
  templateUrl: './zoom-control.component.html',
  styleUrls: ['./zoom-control.component.scss']
})
export class ZoomControlComponent extends MadComponent implements OnInit, OnChanges, AfterViewInit {
  @Input() conserveRatio          = true;
  @Input() dropupPredefinedOption = true;
  @Input() showPredefined         = true;
  @Input() showZoomFactor         = true;
  @Input() zone: Zone             = null;

  @Output() readonly zoomChanged = new EventEmitter<boolean>();

  // Predefined Zoom -> Predefined Zoom Label
  static PredefinedZoomEnumMapList = [
    ['full',        MAD_FULL],
    ['center',      MAD_MenuPositionEnum_eCENTER],
    ['left',        MAD_ZoneJustifyXEnum_eLEFT],
    ['right',       MAD_ZoneJustifyXEnum_eRIGHT],
    ['top',         MAD_ZoneJustifyXEnum_eTOP],
    ['bottom',      MAD_ZoneJustifyXEnum_eBOTTOM],
    ['topLeft',     MAD_MenuPositionEnum_eTOP_LEFT],
    ['topRight',    MAD_MenuPositionEnum_eTOP_RIGHT],
    ['bottomLeft',  MAD_MenuPositionEnum_eBOTTOM_LEFT],
    ['bottomRight', MAD_MenuPositionEnum_eBOTTOM_RIGHT],
  ];

  static PredefinedZoomEnumLabelList = ZoomControlComponent.PredefinedZoomEnumMapList.map((zoneAspect) => zoneAspect[1]);
}

报错信息

Chrome 109.0.0.0 (Mac OS 10.15.7) ERROR
  An error was thrown in afterAll
  Uncaught TypeError: Cannot read properties of undefined (reading 'PredefinedZoomEnumMapList')
  TypeError: Cannot read properties of undefined (reading 'PredefinedZoomEnumMapList')
      at http://localhost:9876/_karma_webpack_/webpack:/src/app/widgets/zoom-control/zoom-control.component.ts:60:61
      at Module.13225 (http://localhost:9876/_karma_webpack_/webpack:/src/app/widgets/zoom-control/zoom-control.component.ts:60:122)

解决方案

原因分析

Angular 15.1的测试编译逻辑调整了类静态属性的初始化顺序,导致在初始化PredefinedZoomEnumLabelList时,ZoomControlComponent类本身还未完全初始化,直接通过类名引用静态属性会出现undefined。

修复方法

方法1:使用this替代类名引用静态属性

在静态属性初始化中,用this指向当前类,避免直接引用类名:

static PredefinedZoomEnumMapList = [/* 原有数组内容 */];
static PredefinedZoomEnumLabelList = this.PredefinedZoomEnumMapList.map((zoneAspect) => zoneAspect[1]);

方法2:改用静态getter延迟计算

将PredefinedZoomEnumLabelList改为静态getter,确保在访问时才计算值:

static PredefinedZoomEnumMapList = [/* 原有数组内容 */];

static get PredefinedZoomEnumLabelList() {
  return this.PredefinedZoomEnumMapList.map((zoneAspect) => zoneAspect[1]);
}

方法3:检查测试文件的mock配置

如果测试中对ZoomControlComponent进行了mock,确保mock没有覆盖静态属性,或者在测试前手动初始化组件类:

// 在测试文件的beforeEach中添加
import { ZoomControlComponent } from './zoom-control.component';

beforeEach(() => {
  // 确保组件类被正确加载
  ZoomControlComponent;
  // 其他测试配置
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 16:01:01