ค้นหาเว็บไซต์

typescript - วิธีการจำลอง ngControl ใน Custom Form Control - การทดสอบหน่วย Angular


ฉันกำลังมองหาตัวอย่างที่มี unit tests สำหรับ Custom Form Control ใน Angular 9 ส่วนนี้ constructor(@Self() private ngControl: NgControl) ทำให้เกิดข้อผิดพลาด: Error: NodeInjector: NOT_FOUND [NgControl] เนื่องจากฉันจำเป็นต้องตั้งค่า value accessor บางวิธี

ฉันกำลังฉีด ngControl ใน constructor เนื่องจากฉันจำเป็นต้องใช้ ngControl ในคอมโพเนนต์ของฉันในภายหลัง นั่นคือสาเหตุที่ฉันไม่ได้ใช้การใช้งานแบบปกติกับ provide: NG_VALUE_ACCESSOR

ฉันกำลังพยายามล้อเลียนมันโดย:

beforeEach(async(() => {
    TestBed.configureTestingModule({
        providers: [
            { provide: NgControl, useValue: new FormControlDirective([], [], [], null) }
        ],
        imports: [FormsModule, ReactiveFormsModule]
    }).compileComponents();

แต่ฉันมีข้อผิดพลาด: No valid value accessor for form control with unspecified name attribute เนื่องจากฉันไม่รู้ว่าควรจะใส่อะไรในพารามิเตอร์ตัวที่ 3 ของฟังก์ชัน FormControlDirective ซึ่งคือ: valueAccessors: ControlValueAccessor[]

มีใครมีไอเดียไหมว่าฉันจะจำลองสิ่งนี้ได้อย่างไร?

คำตอบ #1

ลองล้อเลียนมันแบบนี้:

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();

คำตอบ #2

เนื่องจาก FormControlName ขยายมาจาก NgControl คำตอบที่ยอมรับจะล้มเหลวถ้ามีการเรียกใช้เมธอดใด ๆ ของ ControlValueAccessor (ดูเพิ่มเติมที่นี่) เช่น writeValue()

ตัวอย่างเช่น หนึ่งในการทดสอบของโครงการของเราจะเขียน "ค่าที่ใหม่" เมื่อฟัง ngModelChange เช่นนี้:

this.ngControl.valueAccessor.writeValue(newVal);

แต่เมทอด jasmine.createSpyObj('ngControl', [...]) ล้มเหลวที่นี่ แม้ว่าได้กำหนด writeValue เป็น valueAccessor: { writeValue:() => null } ในอ็อบเจ็กต์สปายแล้ว ผมพบว่าง่ายกว่าที่จะจำลอง ngControl ดังนี้:

let mockNgControl: NgControl = new FormControlName(null, null, null, [{writeValue: () => null, registerOnChange: () => null, registerOnTouched: () => null}], null);

เพราะที่นี่คือตัวสร้างสำหรับ FormControlName

constructor(
    parent: ControlContainer,
    validators: (Validator | ValidatorFn)[],
    asyncValidators: (AsyncValidator | AsyncValidatorFn)[],
    **valueAccessors: ControlValueAccessor[],**
    _ngModelWarningConfig: string | null
);

จากนั้น ngControl ของฉันสามารถถูกส่งเข้าไปในตัวสร้างของไดเร็กทีฟแบบนี้:

let alphanumericDirective = new AlphanumericDirective(mockNgControl);