Angular单元测试中DynamicTestModule报错问题排查
问题:Angular单元测试中formGroup绑定错误及FormGroup声明错误
我正在用Karma和Jasmine编写ProfileListComponent的单元测试,代码如下:
describe('ProfileListComponent', () => { let component: ProfileListComponent; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ [RouterModule.forRoot([])], FormsModule ], declarations: [ ProfileListComponent, ProfilesFiltersComponent, DatatableComponent, ProfileImagePopoverComponent, NgbHighlight, NgbRating, PaginationFooterComponent ], providers: [] }).compileComponents(); TestBed.configureTestingModule({ declarations: [ ProfileListComponent ] }) .createComponent(ProfileListComponent); })); it('should be 4', async(() => { expect(component.add(2,2)).toEqual(4); })) });
ProfileListComponent包含多个子组件,因此我在declarations中引入了这些组件。其中ProfilesFiltersComponent使用了Angular表单,其TS代码如下:
export class ProfilesFiltersComponent implements OnInit { filterForm: FormGroup; }
测试时先报错:
Can't bind to 'formGroup' since it isn't a known property of 'form'
于是我将FormGroup添加到declarations中,却出现新错误:
Failed: Unexpected value 'FormGroup' declared by the module 'DynamicTestModule'. Please add a @Pipe/@Directive/@Component annotation.
请问我哪里操作错误?
问题分析与解决办法
- 第一个错误根源:
formGroup是响应式表单的指令,属于ReactiveFormsModule,你只导入了用于模板驱动表单的FormsModule,Angular无法识别该绑定,因此报错。 - 第二个错误根源:
FormGroup是表单控件类,不是组件、指令或管道,declarations数组仅能存放用@Component、@Directive、@Pipe装饰的类,把FormGroup加入完全不符合规则。 - 额外问题:你在
beforeEach中先后调用两次TestBed.configureTestingModule,第二次配置会覆盖第一次,导致之前声明的子组件全部失效,测试时会找不到这些组件。
正确修正步骤:
- 在测试模块的
imports中添加ReactiveFormsModule(若项目同时使用模板驱动表单,可保留FormsModule); - 移除
declarations中的FormGroup(本来就不该添加); - 仅保留一次
TestBed.configureTestingModule配置,直接在配置后创建组件并完成初始化。
修正后的测试代码示例:
describe('ProfileListComponent', () => { let component: ProfileListComponent; beforeEach(async(() => { await TestBed.configureTestingModule({ imports: [ RouterModule.forRoot([]), FormsModule, ReactiveFormsModule // 新增响应式表单模块 ], declarations: [ ProfileListComponent, ProfilesFiltersComponent, DatatableComponent, ProfileImagePopoverComponent, NgbHighlight, NgbRating, PaginationFooterComponent ], providers: [] }).compileComponents(); // 直接创建组件并赋值给component变量 const fixture = TestBed.createComponent(ProfileListComponent); component = fixture.componentInstance; fixture.detectChanges(); // 触发变更检测,完成组件初始化 })); it('should return 4 when adding 2 and 2', () => { expect(component.add(2, 2)).toEqual(4); }); });
内容的提问来源于stack exchange,提问作者Jesus
相关产品推荐
相关产品推荐

