我正在尝试测试组件内部与其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');
});
答案 0 :(得分:1)
我认为测试的问题在于,在fixture.detectChanges()
中设置fixture
和component
后,您最初不会致电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