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

Angular Jest测试报错:Cannot read properties of undefined (reading 'ɵcmp')求助

问题描述

我有一个父组件,其包含的子组件在模板中使用了该父组件。最初项目构建失败,使用forwardRef后构建成功,但现在父、子组件及其他依赖父组件的组件的Jest单元测试均报错:Cannot read properties of undefined (reading 'ɵcmp'),求解决方法。


相关代码

parent.component.ts

import {Component} from '@angular/core';
import {ChildComponent} from "./child/child.component";
@Component({
  selector: 'parent',
  standalone: true,
  imports: [ChildComponent],
  templateUrl: './parent.component.html',
  styleUrl: './parent.component.css'
})
export class ParentComponent {

}

parent.component.html

Parent
<child [hideParent]="false"/>

parent.component.spec.ts

import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ParentComponent } from './parent.component';

describe('ParentComponent', () => {
 let component: ParentComponent;
 let fixture: ComponentFixture<ParentComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
  imports: [ParentComponent]
})
.compileComponents();

  fixture = TestBed.createComponent(ParentComponent);
  component = fixture.componentInstance;
});

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

child.component.ts

import {Component, forwardRef, input} from '@angular/core';
import {ParentComponent} from "../parent.component";

@Component({
 selector: 'child',
 standalone: true,
 imports: [forwardRef(() => ParentComponent)],
 templateUrl: './child.component.html',
 styleUrl: './child.component.css'
})
export class ChildComponent {
    hideParent = input(false);
}

child.component.html

Child
@if (hideParent()) {
  <parent />
}

child.component.spec.ts

import { ComponentFixture, TestBed } from '@angular/core/testing';

import { ChildComponent } from './child.component';
import {ParentComponent} from "../parent.component";


describe('ChildComponent', () => {
  let component: ChildComponent;
  let fixture: ComponentFixture<ChildComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [ChildComponent, ParentComponent]
    })
   .compileComponents();

   fixture = TestBed.createComponent(ChildComponent);
   component = fixture.componentInstance;
  });

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

// 子组件测试失败

解决方法

1. 测试模块中用forwardRef包裹循环依赖组件

在子组件测试中,直接同时导入循环依赖的两个组件会导致Jest无法正确解析组件定义,用forwardRef包裹父组件导入即可解决:

import { ComponentFixture, TestBed, forwardRef } from '@angular/core/testing';
import { ChildComponent } from './child.component';
import { ParentComponent } from "../parent.component";

describe('ChildComponent', () => {
  let component: ChildComponent;
  let fixture: ComponentFixture<ChildComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        ChildComponent,
        forwardRef(() => ParentComponent)
      ]
    }).compileComponents();

    fixture = TestBed.createComponent(ChildComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

2. 模拟循环依赖组件(推荐)

如果测试不需要依赖真实组件的完整功能,模拟一个极简版本的组件来替代,彻底打破循环依赖:

子组件测试模拟父组件

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ChildComponent } from './child.component';
import { Component, input } from '@angular/core';

// 模拟父组件
@Component({
  selector: 'parent',
  template: '<div>Mock Parent</div>'
})
class MockParentComponent {}

describe('ChildComponent', () => {
  let component: ChildComponent;
  let fixture: ComponentFixture<ChildComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [ChildComponent],
      declarations: [MockParentComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(ChildComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

  it('should render mock parent when hideParent is true', () => {
    component.hideParent.set(true);
    fixture.detectChanges();
    const parentElement = fixture.nativeElement.querySelector('parent');
    expect(parentElement).toBeTruthy();
  });
});

父组件测试模拟子组件

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ParentComponent } from './parent.component';
import { Component, input } from '@angular/core';

// 模拟子组件
@Component({
  selector: 'child',
  template: '<div>Mock Child</div>'
})
class MockChildComponent {
  hideParent = input(false);
}

describe('ParentComponent', () => {
  let component: ParentComponent;
  let fixture: ComponentFixture<ParentComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [ParentComponent],
      declarations: [MockChildComponent]
    }).compileComponents();

    fixture = TestBed.createComponent(ParentComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

3. 确保版本兼容

确认Angular 17与Jest及@angular-builders/jest版本匹配,避免因版本不兼容导致的组件编译解析问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:47:05