在单元测试中调度输入事件时,永远不会触发表单的值更改

Value changes of a form is never triggered when dispatching an input event in a unit test

我正在尝试测试当我在输入中键入时表单上的值是否发生了变化。 项目使用的是Nrwl nx,测试工具是jest

分量:

export class InputNumericComponent implements OnInit, OnDestroy {

  @Input() form: FormGroup;

  @Input() controlName: string; 

  private _changeSubscription: Subscription;

 private get _control(): AbstractControl | null {
    return this.form?.get(this.controlName);
  }

  public ngOnInit(): void {
    if (!this._control) {
       return;
    }
    console.log('init called'); // ok
    this._changeSubscription = this._control.valueChanges
      .pipe(tap((newValue) => this._handleChange(newValue)))
      .subscribe();
  }

  public ngOnDestroy(): void {
    if (this._changeSubscription) {
      this._changeSubscription.unsubscribe();
    }
  }

  private _handleChange(value: string): void {
    console.log('_handleChange'); // never called
  }

  public handleBlur(): void {
    console.log('handleBlur'); // can be called by using dispatchEvent(new Event('blur'));
  }
}

测试文件:

describe('InputNumericComponent', () => {
  let component: InputNumericComponent;
  let fixture: ComponentFixture<InputNumericComponent>;

  configureTestSuite(() => {
    TestBed.configureTestingModule({
      declarations: [InputNumericComponent],
      schemas: [NO_ERRORS_SCHEMA],
    });
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(InputNumericComponent);
    component = fixture.componentInstance;
    component.controlName = 'numeric';
    component.form = new FormGroup({
      numeric: new FormControl(),
    });
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should update form', fakeAsync(() => {
    component.ngOnInit();
    const input = fixture.debugElement.query(By.css('input'));
    input.nativeElement.value = '222';
    // i tried both and others like keydown, keypress, etc..
    input.nativeElement.dispatchEvent(new Event('change'));
    input.nativeElement.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    tick();
    console.log('form', component.form.get('numeric')?.value); // null
    expect(input.form.get('numeric')).toEqual('222');
  }));
});

我不知道为什么但输入事件不会触发 valueChanges,如果我发送 blur 事件 handleBlur 函数被调用但我没有知道如何触发 valueChanges,我试过 keydownkeypress

我尝试直接在输入上发送一个输入事件并且它有效,_handleChange 被调用但不知道为什么在测试中它不起作用。

我试过使用 fixture.nativeElement.querySelector('input') 的其他方法,但它也不起作用。

我做错了什么?

ReactiveFormsModule 添加到您的 TestBed 导入。