角度测试:FormControl valueChanges Observable

Vik*_*kas 6 unit-testing jasmine karma-jasmine angular

我有一个文本输入,我正在听取更改.

零件

name = new FormControl('',Validators.required);

ngOnInit() {
  this.data = 'oldvalue';
  this.checkName();
}

checkName() {
  this.name.valueChanges.subscribe(val=>{
     console.log(val);
     this.data= "newvalue"; // updating Value
  });
}
Run Code Online (Sandbox Code Playgroud)

HTML

<input name="name" formControlName="name">
Run Code Online (Sandbox Code Playgroud)

到目前为止我的尝试:

component.spec.ts

it('should test data field ', () => {
    const fixture = TestBed.createComponent(UserComponent);
    const app=fixture.debugElement.componentInstance;
    const el = fixture.nativeElement.querySelector('input');
    el.value ='something';
    dispatchEvent(new Event(el));
    fixture.detectChanges();
    fixture.whenStable().then(()=>{expect(app.data).toBe('newvalue');
});
Run Code Online (Sandbox Code Playgroud)

问题: 即使填充了输入字段,也不会执行subscribe回调中的代码.

它总是显示:

预期'oldvalue'为'newvalue'.

我也尝试了setValue()方法,但它没有用.它永远不会进入订阅回调

app.name.setValue('vikas');
fixture.detectChanges();
fixture.whenStable().then(()=>{expect(app.data).toBe('newvalue');
Run Code Online (Sandbox Code Playgroud)

在Angular 2测试Angular2组件中引用了更新输入html字段 :测试表单输入值更改但没有运气:(

我错过了什么?

yur*_*zui 12

乍一看,我认为您错过了FormControl未连接到输入的事实,因为您正在使用FormControlName将控件名称作为的指令@Input.

如果您想测试FormControl,那么您可以考虑FormControlDirective采用FormControl如下@Input:

<input name="name" [formControl]="name">
                                  ^^^^^
                      `name` is FormControl instance here not string
Run Code Online (Sandbox Code Playgroud)

现在我们可以确定无论何时我们在输入中更改文本,您FormControl都会触发更改.但是一旦你编写了这样的模板,angular就会要求你ReactiveFormsModule在测试中依赖:

import { ReactiveFormsModule } from '@angular/forms';
....

TestBed.configureTestingModule({
   imports: [
     ReactiveFormsModule  <=== add this
   ],
   declarations: [TestComponent],
});
Run Code Online (Sandbox Code Playgroud)

现在关于你的测试.

1)您必须TestBed通过调用来告诉它执行数据绑定fixture.detectChanges():

const fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); <== add this
Run Code Online (Sandbox Code Playgroud)

2)您应该正确触发输入更改:

el.dispatchEvent(new Event('input'));
Run Code Online (Sandbox Code Playgroud)

这是整个代码:

it('should display original title', () => {
  const fixture = TestBed.createComponent(TestComponent);
  fixture.detectChanges();
  const app = fixture.debugElement.componentInstance;
  const el = fixture.nativeElement.querySelector('input');
  el.value = 'something';
  el.dispatchEvent(new Event('input'));
  fixture.detectChanges();
  fixture.whenStable().then(() => {
    expect(app.data).toBe('newvalue');
  });
});
Run Code Online (Sandbox Code Playgroud)

Plunker示例

  • 我正在使用最后一个 Angular 版本和 Jest,我必须等待 Fixture.whenStable(),然后执行断言 (2认同)