自定义FormControl后Angular单元测试报No value accessor错误如何解决
错误原因
Error: No value accessor for form control 错误本质是Angular在运行时找不到和你模板中绑定的表单控件对应的 值访问器(ControlValueAccessor),你开发环境运行正常但单元测试报错,几乎都是因为测试模块的依赖导入不全、初始化流程不对导致的。
修复步骤
第一步:补全测试模块的依赖导入
开发环境运行正常是因为你项目的全局模块(比如AppModule、SharedModule)已经导入了模板中用到的UI输入组件对应的模块(比如Angular Material的MatFormFieldModule/MatInputModule、PrimeNG的InputTextModule等),但单元测试的TestBed是独立运行的,需要单独导入这些依赖:
beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [MyComponent], imports: [ ReactiveFormsModule, FormsModule, RouterTestingModule, // 这里补全你模板里用到的所有输入组件对应的模块,举例: // MatFormFieldModule, // MatInputModule ] }) // 如果你的组件用了templateUrl、styleUrls,必须加这行编译模板 .compileComponents(); }));
第二步:修正测试初始化流程
确保你在触发变更检测前,组件的ngOnInit已经执行、表单已经初始化完成,标准的测试初始化写法如下:
let component: MyComponent; let fixture: ComponentFixture<MyComponent>; // ... 上面的TestBed配置代码 beforeEach(() => { fixture = TestBed.createComponent(MyComponent); component = fixture.componentInstance; // 第一次触发变更检测,执行ngOnInit初始化表单 fixture.detectChanges(); });
第三步:检查表单绑定写法
不要在模板中同时给同一个控件绑定[formControl]和formControlName,二选一即可:
如果用formGroup包裹,直接写formControlName="reason"就行,不需要额外绑定[formControl]="reasonControl",重复绑定也会触发该错误。
其他代码优化(可选,不影响报错)
你业务组件中初始化FormGroup的代码里重复写了两次reason属性,删掉多余的即可,也不需要加as FormControl类型断言,RequiredControl继承自FormControl,类型天然兼容:
ngOnInit() { this.requestForm = this.formBuilder.group({ reason: this.reasonControl }); }
内容的提问来源于stack exchange,提问作者Luis
相关产品推荐
相关产品推荐

