typescript - Hur man mockar ngControl i anpassad formulärkontroll - Enhetstester Angular
Jag letar efter några exempel med enhetstester för Custom Form Control i Angular 9. Den delen constructor(@Self() private ngControl: NgControl) orsakar ett fel: Error: NodeInjector: NOT_FOUND [NgControl]. Eftersom jag på något sätt behöver sätta value accessor.
Jag injicerar ngControl i konstruktorn eftersom jag behöver använda ngControl senare i min komponent. Det är därför jag inte använde den typiska implementeringen med provide: NG_VALUE_ACCESSOR.
Jag försökte härma det genom att:
beforeEach(async(() => {
TestBed.configureTestingModule({
providers: [
{ provide: NgControl, useValue: new FormControlDirective([], [], [], null) }
],
imports: [FormsModule, ReactiveFormsModule]
}).compileComponents();
Men jag har ett fel: No valid value accessor for form control with unspecified name attribute eftersom jag inte vet vad som ska vara under den tredje parametern av funktionen FormControlDirective som är: valueAccessors: ControlValueAccessor[]
Har någon någon idé om hur jag kan imitera detta?
Svar #1
Försök att driva med det så här:
let mockNgControl: any;
beforeEach(async(() => {
mockNgControl = jasmine.createSpyObj('ngControl', ['value', /* mock other methods required here */]);
TestBed.configureTestingModule({
providers: [
{ provide: NgControl, useValue: mockNgControl }
],
imports: [FormsModule, ReactiveFormsModule]
}).compileComponents();
Svar #2
Eftersom FormControlName utökar NgControl kommer det accepterade svaret att misslyckas om någon av metoderna i ControlValueAccessor (mer här), såsom writeValue(), anropas.
Till exempel skulle ett av våra projekts tester skriva ett "nytt värde" när det lyssnar på en ngModelChange, så här:
this.ngControl.valueAccessor.writeValue(newVal);
men metoden jasmine.createSpyObj('ngControl', [...]) misslyckades här, även när writeValue definierades som valueAccessor: { writeValue:() => null } i spionobjektet. Jag tyckte det var enklare att mocka ett ngControl på följande sätt:
let mockNgControl: NgControl = new FormControlName(null, null, null, [{writeValue: () => null, registerOnChange: () => null, registerOnTouched: () => null}], null);
b/c här är konstruktorn för FormControlName
constructor(
parent: ControlContainer,
validators: (Validator | ValidatorFn)[],
asyncValidators: (AsyncValidator | AsyncValidatorFn)[],
**valueAccessors: ControlValueAccessor[],**
_ngModelWarningConfig: string | null
);
Då kunde mitt ngControl skickas in i konstruktorer för direktiv på detta sätt:
let alphanumericDirective = new AlphanumericDirective(mockNgControl);
