如何测试包含自定义窗体控件的组件?
我有一个像这样的组件
@Component({
selector: 'app-custom-form-control',
templateUrl: '<input>',
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SelectComponent),
multi: true
}
]
})
export class CustomFormControlComponent implements ControlValueAccessor {...}
如您所见,它是一个自定义表单控件.我在要测试的组件中使用它.
As you see it's a custom form control. I use it in a component which I'm going to test.
@Component({
selector: 'app-root',
templateUrl: '<div [formGroup]="form">
<app-custom-form-control formControlName="my_field"></app-custom-form-control>
</div>',
})
export class AppComponent implements OnInit, OnDestroy {...}
那么我该如何模拟app-custom-form-control
进行测试?
So how can I mock app-custom-form-control
for my test?
当前的实现需要一个真正的组件...
The current implementation needs a real component...
beforeEach(async(() => {
const testRouter = new RouterStub();
const testDataService = new DataServiceStub();
TestBed.configureTestingModule({
declarations: [
AppComponent,
CustomFormControlComponent // it is a real stuff
],
imports: [
ReactiveFormsModule
],
providers: [
{ provide: Router, useValue: testRouter },
{ provide: DataService, useValue: testDataService }
],
schemas: [ NO_ERRORS_SCHEMA ]
}).compileComponents();
}));
否则(没有声明该组件)我得到了一个错误Failed: No value accessor for form control with name: app-custom-form-control
Otherwise(without declaration the component) I got an error Failed: No value accessor for form control with name: app-custom-form-control
对Angular应用程序进行测试时,可以遵循两种主要方法(和混合):
When doing tests to Angular applications, there are two main approaches (and a mix) you can follow:
1- 存储不需要的组件,其中
(...)创建并声明组件的存根版本,并 指令在测试中几乎没有作用(...)
(...) you create and declare stub versions of the components and directive that play little or no role in the tests (...)
2- NO_ERRORS_SCHEMA
其中
2- The NO_ERRORS_SCHEMA
which
(...)告诉Angular编译器忽略无法识别的元素和属性(...)
对于这最后一个,编译器在AppComponent
模板中遇到app-custom-form-control
选择器时不会抛出错误.
With this last one the compiler won't throw an error when it encounters the app-custom-form-control
selector in the AppComponent
template.
3- 同时使用这两种技术
选择一种或另一种方法由您决定,因为这取决于您要通过测试的最终目标.
Selecting one approach or another, it's up to you, since it depends on the final goal you aim to with the test.
应用方法1应该是这样的:
Applying approach 1 it would be something like this:
describe('AppComponent', () => {
// component stub
@Component({selector: 'app-custom-form-control', template: ''})
class CustomFormControlComponentStub {}
//...
beforeEach(async(() => {
const testRouter = new RouterStub();
const testDataService = new DataServiceStub();
TestBed.configureTestingModule({
declarations: [
AppComponent,
CustomFormControlComponentStub // it is fake! stuff
],
// ... code omitted
}).compileComponents();
}));
//...
});