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
相关产品推荐
相关产品推荐

