如何在Angle App中触发事件以进行单元测试?

时间:2019-04-09 08:56:37

标签: angular unit-testing

我正在按角度运行单元测试,我想触发一个click事件,这是单击后的下拉列表,它会下拉一个客户编号列表。我想在单元测试中触发该事件,如果成功触发了该事件,我可以更新与单击按钮索引相对应的客户信息。我已附上必要的代码以供参考。请让我知道如何触发点击事件?

//template.html 
<mat-menu #menuFilter="matMenu">
    <button *ngFor="let customer of customers; let i = index" (click)="onCustomerChange(i)" mat-menu-item class="selectCustomerData">{{customer.licenseownerid}}</button>
 </mat-menu>
//angular generated code
<div class="mat-menu-panel ng-trigger ng-trigger-transformMenu ng-tns-c10-1 mat-menu-after
 mat-menu-below ng-star-inserted mat-elevation-z2" role="menu" tabindex="-1" ng-reflect-klass="mat-menu-panel" 
 ng-reflect-ng-class="[object Object]" style="transform-origin: left top;">
    <div class="mat-menu-content">
          <button class="selectCustomerData mat-menu-item ng-star-inserted" mat-menu-item="" role="menuitem" tabindex="0" aria-disabled="false">0LPT_id0306
            <div class="mat-menu-ripple mat-ripple" matripple="" ng-reflect-disabled="false" ng-reflect-trigger="[object HTMLButtonElement]">
            </div>
          </button>
          <button class="selectCustomerData mat-menu-item ng-star-inserted" mat-menu-item="" role="menuitem" tabindex="0" aria-disabled="false">0LPT_id03061
           <div class="mat-menu-ripple mat-ripple" matripple="" ng-reflect-disabled="false" ng-reflect-trigger="[object HTMLButtonElement]">
           </div>
          </button>
       </div>
...and so on
</div>
//component.ts
 onCustomerChange(i) {
    this.customerNumber = this.customers[i].licenseownerid;
    this.customerName = this.customers[i].licenseownername;
}

2 个答案:

答案 0 :(得分:0)

我想提供有关我的问题的更多信息

<button mat-button [matMenuTriggerFor]="menuFilter" class="selectCustomer">
   <span flex>{{customerNumber}}</span>
    <mat-icon class="list-icon">expand_more</mat-icon>
 </button> ------> event number 1 

<mat-menu #menuFilter="matMenu">
  <button *ngFor="let customer of customers; let i = index" (click)="onCustomerChange(i)" 
   mat-menu-item class="selectCustomerData">{{customer.licenseownerid}}</button>
 </mat-menu> -----> event number 2

事件1单击一个按钮将触发事件2,在事件2中,许多按钮显示为下拉菜单。单击任何特定按钮时,将使用相应的按钮索引调用onCustomerchange方法。

主要问题是与事件2对应的所有元素都动态出现和消失。那么,在编写测试时,如何选择一个元素并为其触发事件呢?

答案 1 :(得分:0)

由于第一事件是一个有角度的物质事件,因此我可能会假设点击事件触发了菜单,并且不会在测试用例中包含该特定事件。

我宁愿在测试设置中使用NO_ERRORS_SCHEMA并仅触发您自己的按钮的点击事件:

spec.ts看起来像这样:

@Directive({
  selector: 'mat-menu',
  exportAs: 'matMenu'
})
class DirectiveStub {
}

describe('AppComponent', () => {
    let component: AppComponent;
    let fixture: ComponentFixture<AppComponent>;

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [AppComponent, DirectiveStub],
            schemas: [NO_ERRORS_SCHEMA]
        })
            .compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(AppComponent);
        component = fixture.componentInstance;
    });

    it('should be created', () => {
      fixture.detectChanges();
      expect(component).toBeTruthy();
    });

    it('click on second button', fakeAsync(() => {
      component.customers = [
        {licenseownerid: 'ID_1', licenseownername: 'NAME_1'},
        {licenseownerid: 'ID_2', licenseownername: 'NAME_2'}
        ]
      fixture.detectChanges();

      const buttonDebugElems: DebugElement[] = fixture.debugElement.queryAll(By.css('button'));

      expect(buttonDebugElems.length).toEqual(3);

      buttonDebugElems[2].triggerEventHandler('click', null);
      tick();

      expect(component.customerName).toEqual('NAME_2');
      expect(component.customerNumber).toEqual('ID_2');
    }));
});

重要提示

不幸的是,有必要将指令角材料用于其菜单。那是spec文件顶部的空(未导出)指令。如果您要测试的菜单中有更多组件,建议将该指令移至位于单独文件夹内的单个文件中,例如'test',因此您可以在测试中重用该指令,但不会捆绑到您的应用程序中。


这是一个有效的示例:stackblitz