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

Angular 单元测试失败:如何正确选择并单击组件按钮,angular,typescript,jasmine,karma-runner,Angular,Typescript,Jasmine,Karma Runner,我这里有一个单元测试: 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; sub

我这里有一个单元测试:

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>
浏览图像
搜寻

您就快到了,但是您需要等待click事件被处理,然后再检查是否调用了该方法

1) 最直接的方法是调用显式激活更改检测

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文件中使用

 import { ComponentFixtureAutoDetect, . . . . } from '@angular/core/testing';
.
.
TestBed.configureTestingModule({
  declarations: [ BannerComponent ],
  providers: [
    { provide: ComponentFixtureAutoDetect, useValue: true }
  ]
});
3) 通过使用处理异步按钮单击事件的功能来处理它。然后调用
.whenStable()
,返回承诺

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

您就快到了,但是您需要等待click事件被处理,然后再检查该方法是否已被调用

1) 最直接的方法是调用显式激活更改检测

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文件中使用

 import { ComponentFixtureAutoDetect, . . . . } from '@angular/core/testing';
.
.
TestBed.configureTestingModule({
  declarations: [ BannerComponent ],
  providers: [
    { provide: ComponentFixtureAutoDetect, useValue: true }
  ]
});
3) 通过使用处理异步按钮单击事件的功能来处理它。然后调用
.whenStable()
,返回承诺

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);
});

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

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);
});

比您的具体问题更广泛的是,您不应该模仿您试图测试的组件的某些部分。注入一个mock
imageAPIService
,并确保使用正确的值调用其
getImage
方法-mock协作者和测试行为。这使您可以使用对象控制可观察对象何时发射。我写了一篇关于测试的博文:看,文档中也有指导:比你的具体问题更广泛的是,你不应该模仿你试图测试的组件的部分。注入一个mock
imageAPIService
,并确保使用正确的值调用其
getImage
方法-mock协作者和测试行为。这使您可以使用对象控制可观察对象何时发射。我写了一篇关于测试的博文:看,文档中也有指导: