我正在尝试向my Angular sample中添加一些测试代码。
PostFormComponent
包括一个input
绑定和一个output
事件发射器。
@Component({
selector: 'app-post-form',
templateUrl: './post-form.component.html',
styleUrls: ['./post-form.component.css']
})
export class PostFormComponent implements OnInit, OnDestroy {
@Input() post: Post = { title: '', content: '' };
@Output() saved: EventEmitter<boolean> = new EventEmitter<boolean>();
sub: Subscription;
constructor(private postService: PostService) {}
submit() {
const _body = { title: this.post.title, content: this.post.content };
if (this.post.id) {
this.postService.updatePost(this.post.id, _body).subscribe(
data => {
this.saved.emit(true);
},
error => {
this.saved.emit(false);
}
);
} else {
this.postService.savePost(_body).subscribe(
data => {
this.saved.emit(true);
},
error => {
this.saved.emit(false);
}
);
}
}
ngOnInit() {
console.log('calling ngOnInit::PostFormComponent...');
}
ngOnDestroy() {
console.log('calling ngOnDestroy::PostFormComponent...');
if (this.sub) {
this.sub.unsubscribe();
}
}
}
组件模板:
<form id="form" #f="ngForm" name="form" class="form" (ngSubmit)="submit()">
<p>
<mat-form-field fxFlex>
<input matInput
id="title"
name="title"
#title="ngModel"
[(ngModel)]="post.title"
required/>
<mat-error align="start" *ngIf="title.hasError('required')">
Post Title is required
</mat-error>
</mat-form-field>
</p>
<p>
<mat-form-field fxFlex>
<textarea matInput
#content="ngModel"
name="content"
id="content"
[(ngModel)]="post.content"
rows="8"
required
minlength="10">
</textarea>
<mat-error align="start" *ngIf="content.hasError('required')">
Post Content is required
</mat-error>
<mat-error align="start" *ngIf="content.hasError('minlength')">
At least 10 chars
</mat-error>
</mat-form-field>
</p>
<p>
<button mat-button mat-raised-button color="primary" type="submit" [disabled]="f.invalid || f.pending"> {{'save'}}</button>
</p>
</form>
我试图为此组件添加一些测试。
describe('Component: PostFormComponent(input & output)', () => {
let component: PostFormComponent;
let fixture: ComponentFixture<PostFormComponent>;
let componentDe: DebugElement;
let savePostSpy: jasmine.Spy;
// Create a fake service object with spies
const postServiceSpy = jasmine.createSpyObj('PostService', [
'savePost',
'updatePost'
]);
beforeEach(() => {
TestBed.configureTestingModule({
imports: [BrowserAnimationsModule, SharedModule],
declarations: [PostFormComponent],
// provide the component-under-test and dependent service
providers: [
// { provide: ComponentFixtureAutoDetect, useValue: true },
{ provide: PostService, useValue: postServiceSpy }
]
}).compileComponents();
fixture = TestBed.createComponent(PostFormComponent);
component = fixture.componentInstance;
componentDe = fixture.debugElement;
fixture.detectChanges();
});
it('should raise `saved` event when the form is submitted (triggerEventHandler)', fakeAsync(() => {
const formData = { title: 'Test title', content: 'Test content' };
// trigger initial data binding
component.post = formData;
let saved = false;
savePostSpy = postServiceSpy.savePost
.withArgs(formData)
.and.returnValue(of({}));
// Make the spy return a synchronous Observable with the test data
component.saved.subscribe((data: boolean) => (saved = data));
// componentDe.triggerEventHandler('submit', null);
component.submit();
tick();
fixture.detectChanges();
expect(saved).toBeTruthy();
expect(savePostSpy.calls.count()).toBe(1, 'savePost called');
}));
});
问题是,如果我使用componentDe.triggerEventHandler('submit', null)
,则测试将失败。但是调用component.submit()
效果很好。
答案 0 :(得分:1)
您要触发表单上的提交事件,而不是整个组件,因此请首先使用查询来隔离表单元素:
const formElement = componentDe.query(By.css('form#form'));
formElement.triggerEventHandler('submit', null);
答案 1 :(得分:1)
我认为您应该通过点击sumit按钮来触发事件
let submitButtonEL: DebugElement = fixture.debugElement.query(By.css('button'));
submitButtonEL.nativeElement.click()
直接使用form.triggerEventHandler('submit', null);
触发表单的commitevent并不能真正保证存在UI触发事件的方法。
编写一个测试,单击“提交”按钮,然后检查是否触发了“提交事件”,确实可以保证