Angular 6单元测试报错:无法绑定属性及组件未识别求助
嘿,我看你在Angular单元测试里碰到了组件识别和属性绑定的问题,咱们来一步步拆解解决它。
问题背景
你有一个模块化的Angular应用,DonutCardComponent被放在CoreModule里声明并导出,但单元测试时却报错说无法识别这个组件的输入属性,也找不到组件本身。
先理下你的应用结构和关键代码:
应用简化结构
-app -Core -donut-card -donut-card-component.html -donut-card-component.spec.ts -donut-card-component.ts -core.module.ts -app.module.ts
关键代码片段
donut-card.component.ts(组件定义)
import { Component, Input } from '@angular/core'; import { DonutChartConfig } from 'patternfly-ng/chart'; @Component({ selector: 'ssc-donut-card', templateUrl: './donut-card.component.html' }) export class DonutCardComponent { @Input() chartTitle: string; @Input() titleLink: Array<string>; @Input() donutConfig: DonutChartConfig; @Input() chartData: Array<any>; }
core.module.ts(模块配置)
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouterModule } from '@angular/router'; import { DonutCardComponent } from './donut-card/donut-card.component'; @NgModule({ imports: [ BrowserModule, DonutChartModule, RouterModule ], declarations: [ DonutCardComponent ], exports: [ DonutCardComponent ] }) export class CoreModule {}
报错核心内容
Failed: Template parse errors:
Can't bind to 'chartTitle' since it isn't a known property of 'ssc-donut-card'.
...
'ssc-donut-card' is not a known element:
...
问题原因
测试模块完全独立于你的应用模块,当前测试配置里只声明了DonutCardComponent,但没有导入它依赖的DonutChartModule(模板里用到了pfng-donut-chart);另外如果是测试使用该组件的父组件,还需要确保父组件的测试模块能访问到ssc-donut-card。
解决方案
方案1:直接导入CoreModule(推荐)
因为CoreModule已经正确声明并导出了DonutCardComponent,还包含了它的依赖模块,所以在测试配置里直接导入CoreModule就能一次性解决所有依赖问题:
修改donut-card.component.spec.ts的测试模块配置:
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { DonutCardComponent } from './donut-card.component'; import { CoreModule } from '../core.module'; // 新增导入 describe('DonutCardComponent', () => { let component: DonutCardComponent; let fixture: ComponentFixture<DonutCardComponent>; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule, CoreModule ], // 导入CoreModule // 移除declarations里的DonutCardComponent,CoreModule已经导出它了 }) .compileComponents(); fixture = TestBed.createComponent(DonutCardComponent); component = fixture.componentInstance; fixture.detectChanges(); })); it('should create', () => { expect(component).toBeTruthy(); }); });
方案2:单独声明组件并导入依赖模块
如果你不想导入整个CoreModule,可以手动声明DonutCardComponent,同时必须导入它模板里用到的DonutChartModule:
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { RouterTestingModule } from '@angular/router/testing'; import { DonutCardComponent } from './donut-card.component'; import { DonutChartModule } from 'patternfly-ng/chart'; // 新增依赖模块导入 describe('DonutCardComponent', () => { let component: DonutCardComponent; let fixture: ComponentFixture<DonutCardComponent>; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule, DonutChartModule ], // 导入依赖模块 declarations: [ DonutCardComponent ] }) .compileComponents(); fixture = TestBed.createComponent(DonutCardComponent); component = fixture.componentInstance; fixture.detectChanges(); })); it('should create', () => { expect(component).toBeTruthy(); }); });
针对父组件测试的额外提示
如果报错来自使用ssc-donut-card的父组件(比如你报错里提到的ScoresDonutCardComponent),那父组件的测试模块也需要做同样的配置:要么导入CoreModule,要么声明DonutCardComponent并导入DonutChartModule。
避坑提醒
别用NO_ERRORS_SCHEMA来跳过这些错误,虽然能让测试通过,但会隐藏模板里的真实问题,比如拼写错误、缺失依赖等,不利于测试的准确性。
内容的提问来源于stack exchange,提问作者Nirzari

