如何在断言之前将组件状态与 html-input 同步?
how to synchronise component state with html-input before assertion?
我正在尝试测试组件内部结构与其 HTML 之间的交互。
在下面的测试代码中,我有一个带有输入字段的应用程序组件,它使用双向绑定链接到组件内的一个属性。
Test1 使用 fixture.detectChanges
通过并等待它稳定。因此,在此测试中,组件测试属性与输入字段同步。
但是,由于组件尚未使用新的测试属性值更新,因此测试 2 失败。那么,在进入断言之前同步更改我错过了什么或做错了什么?
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');
});
在第二次测试中,您必须添加:
el.dispatchEvent(new Event('input'));
在执行 expect 之前,而不是在
之后
然后你还必须添加
fixture.detectChanges();
在做 expect 之前
所以这样写你的第二个测试:
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
我认为您测试的问题在于,您在 beforeEach
.[=19 中设置 fixture
和 component
后,最初从未调用 fixture.detectChanges()
=]
Check
this
stackblitz for a working version of your test.
我添加了第二个 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();
});
});
我正在尝试测试组件内部结构与其 HTML 之间的交互。
在下面的测试代码中,我有一个带有输入字段的应用程序组件,它使用双向绑定链接到组件内的一个属性。
Test1 使用 fixture.detectChanges
通过并等待它稳定。因此,在此测试中,组件测试属性与输入字段同步。
但是,由于组件尚未使用新的测试属性值更新,因此测试 2 失败。那么,在进入断言之前同步更改我错过了什么或做错了什么?
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');
});
在第二次测试中,您必须添加:
el.dispatchEvent(new Event('input'));
在执行 expect 之前,而不是在
之后然后你还必须添加
fixture.detectChanges();
在做 expect 之前
所以这样写你的第二个测试:
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
我认为您测试的问题在于,您在 beforeEach
.[=19 中设置 fixture
和 component
后,最初从未调用 fixture.detectChanges()
=]
Check this stackblitz for a working version of your test.
我添加了第二个 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();
});
});