如何在断言之前将组件状态与html-input同步?

时间:2019-01-20 15:46:21

标签: angular jasmine karma-jasmine angular-test

我正在尝试测试组件内部与其HTML之间的交互。

在下面的测试代码中,我有一个带有输入字段的应用程序组件,该组件使用双向绑定链接到该组件内的属性。

Test1通过使用fixture.detectChanges并等待其稳定。因此,在此测试中,组件test-attribute与输入字段同步。

但是,由于未使用新的test-attribute值更新组件,因此test2失败。那么,我在进入断言之前缺少什么同步同步所做的更改?

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  test = 'hello';
}

import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
import {BrowserModule, By} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
import {ComponentFixture} from '../../node_modules/@angular/core/testing';
import {detectChanges} from '../../node_modules/@angular/core/src/render3';
describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        FormsModule
      ],
      declarations: [
        AppComponent,
      ],
    }).compileComponents();
      fixture = TestBed.createComponent(AppComponent);
      component = fixture.componentInstance;
    });
  it('test1', () => {
    const inputElement = fixture.debugElement.query(By.css('input'));
    const el = inputElement.nativeElement;
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      expect(el.value).toBe('hello');
    })

  });
  it('test2', () => {
    const inputElement = fixture.debugElement.query(By.css('input'));
    const el = inputElement.nativeElement;
    el.value = 'test';
    expect(el.value).toBe('test');
    el.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      expect(component.test).toBe('test');
    })
  });
});
<div>
  <input [(ngModel)]="test" type="text">
  <p>{{test}}</p>
</div>

我接受了下面的答案,并查看了答案中的最低要求,以使我的考试通过。关键似乎在于将Fixture.detectChanges()移至beforeEach()函数。

除了在beforeEach中添加了fix.detectChanges之外,我认为这是我通过测试所需要的最低要求。似乎完成和fixture.whenStable并不是必需的。

it('test2', () => {
   const inputElement = fixture.debugElement.query(By.css('input'));
   const el = inputElement.nativeElement;
   el.value = 'test';
   el.dispatchEvent(new Event('input'));
   expect(component.test).toBe('test');
});

2 个答案:

答案 0 :(得分:1)

我认为测试的问题在于,在fixture.detectChanges()中设置fixturecomponent后,您最初不会致电beforeEach

  

检查   this   stackblitz获得测试的有效版本。

我添加了第二个beforeEach,其中fixture.detectChanges被称为:

beforeEach(() => {
  fixture = TestBed.createComponent(AppComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
});

这是失败的(现在正在工作)测试:

it('test2', (done) => {
  const inputElement = fixture.nativeElement.querySelector('input');
  inputElement.value = 'test';

  const inputEvent = document.createEvent('Event');
  inputEvent.initEvent('input', true, true);
  inputElement.dispatchEvent(inputEvent);

  fixture.detectChanges();
  fixture.whenStable().then(() => {
    expect(component.test).toBe('test');
    done();
  });
});

答案 1 :(得分:0)

在第二个测试中,您必须添加以下内容:

el.dispatchEvent(new Event('input'));

在做期望之前,而不是在

之后

然后您还必须添加

fixture.detectChanges();也要先完成期望

所以这样编写第二个测试:

it('test2', async(() => {
    const inputElement = fixture.debugElement.query(By.css('input')).nativeElement;
    inputElement.value = 'test';
    inputElement.dispatchEvent(new Event('input'));
    fixture.detectChanges();
    fixture.whenStable().then(() => {
      expect(component.test).toBe('test');
    })
}));

您必须将async添加到it函数中,因为ngModel是异步的。

或者,您也可以使用fakeAsync