单元测试失败:如何正确 select 并单击组件按钮

Unit test failing: How do I properly select and click a components button

我这里有一个单元测试:

fit('should call getImageByID upon submit when a search id is present', () => {
    spyOn(component, 'getImageById');
    component.searchId = '1';
    submit = fixture.debugElement.query(By.css('#getimagebyid')).nativeElement;
    submit.click();
    expect(component.getImageById).toHaveBeenCalled();
  });

单元测试失败,因为没有满足预期(方法没有被执行),我错过了什么?这是未被触发的组件方法:

getImageById() {
        this.imageAPIService.getImage(this.searchId).subscribe(res => {
            this.response.id = (res as any).id;
            this.response.image = (res as any).image;
        });
    }

和组件的 html:

<h4>Browse Images</h4>
<div class="row">
    <img *ngIf="response.id != null" [src]="response.image[0].url" height="200">
</div>
<div class="row">
    <input [(ngModel)]="searchId" type="text">
    <button class="btn btn-block btn-primary" id="getimagebyid" [disabled]="!searchId" (click)="getImageById(searchId)">Search</button>
</div>

大功告成,但需要等待点击事件处理完毕,再检查方法是否被调用。

1) 最直接的方法是调用 detectChanges() 显式激活变化检测。

it('clicking on settings icon will trigger openModal method', () => {
  spyOn(component, 'getImageById');
  component.searchId = '1';
  submit = fixture.debugElement.query(By.css('#getimagebyid')).nativeElement;
  submit.click();
  fixture.detectChanges();
  expect(component.getImageById).toHaveBeenCalled();
  });

2) 或者,您可以在 .spec 文件中使用 automatic change detection

 import { ComponentFixtureAutoDetect, . . . . } from '@angular/core/testing';
.
.
TestBed.configureTestingModule({
  declarations: [ BannerComponent ],
  providers: [
    { provide: ComponentFixtureAutoDetect, useValue: true }
  ]
});

3) 使用async()功能处理异步按钮点击事件。随后调用 .whenStable(),即 returns 承诺。

import { async, . . . . } from '@angular/core/testing';
.
.
it('clicking on settings icon will trigger openModal method', async(() => {
  spyOn(component, 'getImageById');
  component.searchId = '1';
  submit = fixture.debugElement.query(By.css('#getimagebyid')).nativeElement;
  submit.click();

  fixture.whenStable().then(() => {
    expect(component.getImageById).toHaveBeenCalled();
  });
}));

我能想到的最简单的解决方案是:

it('should call getImageByID upon submit when a search id is present', () => {
  const spy = spyOn(component, 'getImageById');
  fixture.debugElement.query(By.css('#getimagebyid'))
    .triggerEventHandler('click', null);
  expect(spy).toHaveBeenCalledTimes(1);
});