【问题标题】:How to trigger an event in angular app for unit testing?如何在角度应用程序中触发事件以进行单元测试?
【发布时间】:2019-04-09 08:56:36
【问题描述】:

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

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

【问题讨论】:

  • 我还是有点不确定你到底想测试什么。您是否尝试触发第一个按钮,然后让其他按钮可见,以便您可以单击其中一个按钮,或者是否足以测试您自己的按钮的单击方法,因为另一个单击机制是可能已经测试过的材料组件?
  • 我正在尝试触发第一个按钮以使其他按钮可见,因此我可以单击这些按钮中的一个。单击其中一个按钮时。单击按钮的索引是按钮传递给 onChangeCustomer(index)。我想监视这个方法是否被调用,以及它是否使用正确的索引调用
  • 是否有可能测试没有角度编译的模板???
  • “没有角度编译的”是什么意思?如果您想测试包括材料组件在内的整个过程,您需要模拟指令 matMenuTriggerFor,据我从您的示例中可以看出,该指令似乎负责显示您要测试的按钮。问题是它是否真的值得付出努力,因为材料组件本身可能已经过很好的测试。测试您自己的按钮还不够吗?因此,存根客户并单击客户的按钮并期望新的客户 ID 和客户名称就足够了
  • 这就是我将如何测试该组件stackblitz.com/edit/testing-mat-menu

标签: angular unit-testing


【解决方案1】:

由于第一个事件是一个角度材料事件,我可能会假设在点击时触发 mat-menu 是有效的,并且不会在测试用例中包含这个特定事件。

我宁愿在测试设置中使用 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');
    }));
});

重要提示

不幸的是,有必要对用于其菜单的指令角度材质进行存根。那是规范文件顶部的空(未导出)指令。如果您想测试更多带有该菜单的组件,则可以将该指令移动到放置在单独文件夹中的单个文件中,例如'test',因此您可以在测试中重用该指令,但不会捆绑到您的应用程序中。


这是一个工作示例:stackblitz

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-03
    • 2015-10-09
    • 2020-08-01
    • 2020-07-10
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    • 2021-01-02
    相关资源
    最近更新 更多