Angular 单元测试 - TypeError:无法读取未定义的属性“名称”

弗里茨6

我正在使用 Jasmine/Karma 运行 Angular 单元测试。目前收到以下错误:

TypeError: Cannot read property 'name' of undefined
    at ReplicateListComponent_Template (ng:///ReplicateListComponent.js:221:64)
    at executeTemplate (http://localhost:9876/_karma_webpack_/vendor.js:49857:9)
    at refreshView (http://localhost:9876/_karma_webpack_/vendor.js:49723:13)
    at refreshComponent (http://localhost:9876/_karma_webpack_/vendor.js:50894:13)
    at refreshChildComponents (http://localhost:9876/_karma_webpack_/vendor.js:49520:9)

ReplicateListComponent.js 的第 221 行:

        jit___property_12('title',jit___pipeBind1_9(13,28,'upload_replicate_tooltip'))('routerLink',
            jit___pureFunction1_10(32,_c1,ctx.managementConfig.name));
        jit___advance_6(3);

ctx.managementConfig.name- ctx 没有命名的变量managementConfig- 见截图。

在此处输入图片说明

单元测试代码:

  let component: ReplicateViewComponent;
  let fixture: ComponentFixture<ReplicateViewComponent>;
  let params: Subject<Params>;
  let queryParams: Subject<Params>;
  let mockManagementService: jasmine.SpyObj<ManagementConfigService>;
  let getManagementConfig: Subject<IManagementConfig>;
  let environmentSwitched: Subject<string>;

  beforeEach(async () => {
    params = new Subject<Params>();
    queryParams = new Subject<Params>();
    mockManagementService = jasmine.createSpyObj<ManagementConfigService>([ 'getManagementConfig', 'getCurrentManagementConfig', 'findManagementConfig', 'environmentSwitched' ]);
    getManagementConfig = new Subject<IManagementConfig>();
    environmentSwitched = new Subject<string>();
...
    await TestBed.configureTestingModule({
      imports: [
        HttpClientTestingModule,
        ToastrModule.forRoot({}),
        RouterTestingModule.withRoutes([
          { path: ':env/replicates', component: DummyComponent },
        ]),
...
      ],
      declarations: [
        ReplicateViewComponent,
...
        ReplicateListComponent,
...
      ],
      providers: [
        { provide: ManagementConfigService, useValue: mockManagementService },
        { provide: ActivatedRoute, useValue: ACTIVATED_ROUTE },
        { provide: RuntimeConfig, useValue: RUNTIME_CONFIG },
...
      ],
    })
    .compileComponents();

    mockManagementService.getManagementConfig.and.returnValue(getManagementConfig);
    mockManagementService.getCurrentManagementConfig.and.returnValue(RUNTIME_CONFIG.environments[0]);
    mockManagementService.findManagementConfig.and.returnValue(RUNTIME_CONFIG.environments[0]);
    mockManagementService.environmentSwitched.and.returnValue(environmentSwitched);
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(ReplicateViewComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
    component.list.managementConfig = RUNTIME_CONFIG.environments[0];
    component.list.replicates = REPLICATIONS;
    component.details.replicate = REPLICATIONS[0];

    const router = TestBed.inject(Router);
    router.initialNavigation();

    getManagementConfig.next(RUNTIME_CONFIG.environments[0]);
    environmentSwitched.next(RUNTIME_CONFIG.environments[0].name);
    params.next({ id: '11111111-1111-1111-1111-111111111111' });
  });

  it('should create', () => {
    expect(component).toBeTruthy();
    expect(component.list).toBeTruthy();
    expect(component.details).toBeTruthy();
  });

我期望有一个名为 的变量的原因managementConfig

export class ReplicateListComponent extends BaseContainerComponent implements OnInit {

  managementConfig: IManagementConfig;
...
  ngOnInit(): void {
    this.subs.add(
      this.route.params.subscribe(
        (params: Params) => {
          this.managementConfig = this.managementService.findManagementConfig(params.env);

ReplicateListComponent 的 HTML 的违规部分 - 请参阅 routerLink

    <div class="my-auto ml-auto">
      <a data-cy="batchReplicateLink" [title]="'upload_replicate_tooltip' | translate" [routerLink]="[ '/', managementConfig.name, 'replicates', 'batch']" queryParamsHandling="preserve">
        <i class="icons8-sm icons8-Copy"></i>{{ 'replicate_batch_link' | translate }}
      </a>
    </div>

ReplicateListComponent.js 与没有错误的 AssetListComponent.js 非常相似。从截图中可以看出,AssetListComponent 的上下文中有一个 managementConfig:

在此处输入图片说明

AssetListComponent 的 routerLink HTML 本质上是一样的:

      <a
        data-cy="uploadLink"
        [title]="'upload_asset_tooltip' | translate"
        [routerLink]="[ '/', managementConfig.name, 'assets', 'upload']"
        [queryParamsHandling]="'preserve'"
        *ngIf="managementConfig?.upload"
      >
        <i class="icons8-sm icons8-Upload"></i>{{ 'asset_list_upload_link' | translate }}
      </a>

Backend code of AssetListComponent:

export class AssetListComponent extends BaseContainerComponent implements OnInit {

  managementConfig: IManagementConfig;
...
  ngOnInit(): void {
    this.subs.add(
      this.route.params.subscribe(
        (params: Params) => {
          this.managementConfig = this.managementService.findManagementConfig(params.env);

  1. What caused the error?
  2. What is the fix?
  3. Why is the error in ReplicateListComponent but not AssetListComponent?

Thanks.

AliF50

1.) The error is caused because the first fixture.detectChanges() you call, managementConfig is undefined at that point in time. Your other component, there is an *ngIf where this issue doesn't happen where it will be explained in #3.

2.) The fix would be to hide this HTML until managementConfig is truthy:

<div class="my-auto ml-auto" *ngIf="managementConfig">
      <a data-cy="batchReplicateLink" [title]="'upload_replicate_tooltip' | translate" [routerLink]="[ '/', managementConfig.name, 'replicates', 'batch']" queryParamsHandling="preserve">
        <i class="icons8-sm icons8-Copy"></i>{{ 'replicate_batch_link' | translate }}
      </a>
    </div>

3.) The error is in one place but not the other because in the second one you have an *ngIf:

The *ngIf="managementConfig?.upload" first checks if managementConfig exists (with the question mark) and if it does, does upload exist in the object, if it does, go ahead and show this HTML mark up.

如果您删除 this *ngIf,我认为这里也会发生错误。

<a
        data-cy="uploadLink"
        [title]="'upload_asset_tooltip' | translate"
        [routerLink]="[ '/', managementConfig.name, 'assets', 'upload']"
        [queryParamsHandling]="'preserve'"
        *ngIf="managementConfig?.upload"
      >
        <i class="icons8-sm icons8-Upload"></i>{{ 'asset_list_upload_link' | translate }}
      </a>

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Angular 8:ActivatedRoute 上的 Jasmine 单元测试,TypeError:无法读取未定义的属性“父”

Angular 4单元测试错误“ TypeError:无法读取未定义的属性'subscribe'”

单元测试 Angular 4 出现错误“TypeError:无法读取未定义的属性“订阅”

运行npm测试(Angular 2单元测试)后无法读取未定义的属性“ subscribe”

TypeError:在angular2中执行单元测试时,无法读取未定义故障的属性“快照”

Angular 2单元测试“无法读取未定义的属性'unsubscribe'”

Angular 2单元测试-无法读取未定义的属性“ root”

Angular 单元测试为 Http Post 返回“无法读取未定义的属性”

类型错误:在单元测试 Angular 6 时无法读取未定义的属性“查询”

angular2单元测试:无法读取componentInstance.method()的属性未定义

Angular 单元测试自定义验证器无法读取未定义的属性(读取“dobLengthValidator”)

对具有路由器依赖项的 Angular 服务进行单元测试:“TypeError:无法读取未定义的属性‘导航’”

Angular2-单元测试可观察到的错误“无法读取未定义的属性'subscribe'”

Angular 2单元测试错误无法获取未定义或空引用的属性“ preventDefault”

无法设置未定义的属性“http” - Angular 单元测试

Angular 2单元测试-@ViewChild未定义

Angular-TypeError:无法读取未定义的属性“名称”

Angular Component 测试 TypeError:无法读取未定义的属性“订阅”

TypeError:无法读取未定义的属性“ id”-Angular 8测试

单元测试 Angular 属性指令

Angular 中的单元测试无法读取属性

Jasmine 单元测试 - TypeError:无法读取未定义的属性(读取“管道”)

TypeError:$ scope在Jasmine的Angular控制器单元测试中未定义

角单元测试:TypeError:无法读取未定义的属性“ root”

玩笑和酶单元测试:TypeError:无法读取未定义的属性“ push”

反应开玩笑的单元测试用例TypeError:无法读取未定义的属性'then'

渲染错误:“TypeError:无法读取未定义的属性‘_t’”在单元测试中使用 Jest

Angular 2单元测试:找不到名称“描述”

在 Angular 单元测试中从 HTML 获取 routerLink 属性