簡體   English   中英

如何在斷言之前將組件狀態與 html-input 同步?

[英]how to synchronise component state with html-input before assertion?

我正在嘗試測試組件內部與其 HTML 之間的交互。

在下面的測試代碼中,我有一個帶有輸入字段的應用程序組件,它使用雙向綁定鏈接到組件內的一個屬性。

Test1 通過使用fixture.detectChanges並等待它穩定。 因此,在此測試中,組件測試屬性與輸入字段同步。

但是,由於組件尚未使用新的 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 中添加 fixture.detectChanges 之外,我相信這是通過測試所需的最低要求。 似乎不需要 done 和 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');
});

我認為您的測試的問題在於,在您在beforeEach設置fixturecomponent后,您最初從未調用過fixture.detectChanges()

檢查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();
  });
});

在第二個測試中,您必須添加以下內容:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM