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

Angular嵌套React组件Jest测试报错:无法读取'ɵcmp'属性

Angular封装React组件后Jest单元测试报错:Cannot read properties of undefined (reading 'ɵcmp')

问题背景

开发Angular应用时引入第三方React组件,完成Angular封装组件后运行正常,但Jest单元测试全部报错,提示Cannot read properties of undefined (reading 'ɵcmp')。

相关代码及配置

React组件

export const ReactoComponent: FunctionComponent<IProps> = (props: IProps) => {
  return (
    <div className={`reacto-component`}>
      <span>Counter: {props.counter}</span>
    </div>
  );
};

Angular封装组件

@Component({
  selector: 'wrapper',
  standalone: true,
  templateUrl: './wrapper.component.html',
})
export class WrapperComponent implements AfterViewInit {
  counter = 42;

  @ViewChild('myReactContainer', { static: false }) container!: ElementRef;

  ngAfterViewInit() {
    this.render();
  }

  render() {
    const { counter } = this;
    ReactDOM.render(
      <div className={'wrapper'}>
        <ReactoComponent counter={counter} />
      </div>,
      this.container.nativeElement
    );
  }
}

测试代码

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

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

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

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

Jest配置

module.exports = {
  preset: 'jest-preset-angular',
  setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
  globalSetup: 'jest-preset-angular/global-setup',
  testMatch: ['**/*.test.ts'],
};

报错信息

Expected value   undefined
Received:
  undefined

Message:
  Cannot read properties of undefined (reading 'ɵcmp')

解决方案

这个报错本质是Jest测试环境中React相关代码未被正确处理,Angular测试工具误将React组件当作Angular组件解析,导致元数据缺失。可通过以下步骤修复:

  • 模拟React及ReactDOM核心方法
    在全局测试配置文件(如setup-jest.ts)中,模拟ReactDOM.render方法,避免测试时实际执行React组件渲染逻辑:

    jest.mock('react-dom', () => ({
      render: jest.fn(),
    }));
    
  • Mock组件内的render方法
    在测试用例中提前mock封装组件的render方法,避免触发真实的React渲染流程:

    describe('WrapperComponent', () => {
      let component: WrapperComponent;
      let fixture: ComponentFixture<WrapperComponent>;
    
      beforeEach(async () => {
        await TestBed.configureTestingModule({
          imports: [WrapperComponent],
        }).compileComponents();
    
        fixture = TestBed.createComponent(WrapperComponent);
        component = fixture.componentInstance;
        // 模拟render方法,阻止真实执行
        jest.spyOn(component, 'render').mockImplementation(() => {});
        fixture.detectChanges();
      });
    
      it('should create', () => {
        expect(component).toBeTruthy();
      });
    
      it('should trigger render after view init', () => {
        expect(component.render).toHaveBeenCalled();
      });
    });
    
  • 调整Jest配置,兼容React文件
    修改jest.config.js,添加React JSX/TSX文件的处理规则:

    module.exports = {
      preset: 'jest-preset-angular',
      setupFilesAfterEnv: ['<rootDir>/setup-jest.ts'],
      globalSetup: 'jest-preset-angular/global-setup',
      testMatch: ['**/*.test.ts'],
      transform: {
        '^.+\\.(ts|js|html)$': 'jest-preset-angular',
        '^.+\\.(jsx|tsx)$': 'babel-jest',
      },
      moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'],
    };
    

    同时安装必要依赖:

    npm install --save-dev babel-jest @babel/preset-react @babel/preset-typescript
    

    创建.babelrc配置文件:

    {
      "presets": [
        "@babel/preset-react",
        "@babel/preset-typescript"
      ]
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 10:45:16