【问题标题】:Angular2 + Jasmine Event ObjectAngular2 + Jasmine 事件对象
【发布时间】:2017-12-08 10:17:51
【问题描述】:

我有这个简单的方法需要测试:

  public onLayerContainerClick(event: Event): void {
    event.stopPropagation();
    event.preventDefault();
    if (event.srcElement.classList.contains('dpm-info__layerContainer')) {
     this.closeInfoLayer(event);
    }
  }

我的目标实际上是增加组件的代码覆盖率。如果我测试是这样的:

  it( 'should close on info container click', () => {
    spyOn( component, 'onLayerContainerClick' );
    const el: DebugElement = fixture.debugElement.query( By.css( '.dpm-info__layerContainer' ) );
    el.triggerEventHandler( 'click', null );
    expect( component.onLayerContainerClick ).toHaveBeenCalled();
  } );

测试正常,但 instanbul 显示“功能未涵盖”。所以我想,我需要显式调用该函数?为此,我需要一个完整的事件对象,包括(至少) srcTarget 属性。如何在单元测试中定义这样的事件?

【问题讨论】:

    标签: angular jasmine dom-events istanbul angular2-testing


    【解决方案1】:

    您必须在测试中使用模拟事件调用该函数。 component.onLayerContainerClick({ srcElement: { value: 'mock_value' } });

    然后写下你期望的内容

    expect( component.closeInfoLayer ).toHaveBeenCalled();

    也许这个https://angular.io/guide/testing#triggereventhandler 也有帮助

    【讨论】:

    • 挑战是 Typescript,它期望传入onLayerContainerClick 的参数是Event 类型。只传递一个带有 srcTarget 属性的对象并不能削减它 - 我得到一个类型错误。
    • 好的,你能在每次测试开始时也发布beforeEach 吗?顺便说一句,如果你尝试 component.onLayerContainerClick({ srcElement: { value: 'mock_value' } });或 你有错误吗?
    • @pop 不是挑战。这些类型可以帮助您,而不是制造障碍。您可以使用<any>arg<Event><any>arg 传递您需要的任何参数。
    • 是的,模拟输入数据应该不是问题
    • 嗯,我已经克服了第一道障碍,并且能够构造一个 Event 类型的对象,正如你们所说的那样。但是(在这里我们开始),组件event.srcElement.classList.contains 中的这一行期望classListDOMTokenList 类型,它有自己的方法和属性(见这里stackoverflow.com/questions/29172515/…)。
    【解决方案2】:

    感谢 estus 和 DrNio,我提出了这个测试,它使 istanbul 代码覆盖率高,并且没有任何类型问题:

      it( 'should close on info container click', () => {
        spyOn( component, 'closeInfoLayer' );
        const el: HTMLElement = fixture.debugElement.query(By.css('.dpm-info__layerContainer')).nativeElement;
        const mockEvent: Event = <Event><any>{
          srcElement: {
            classList: el.classList
          },
          stopPropagation: <any>( ( e: any ) => { /**/ }),
          preventDefault: <any>( ( e: any ) => { /**/ }),
        };
    
        component.onLayerContainerClick( mockEvent );
        expect( component.closeInfoLayer ).toHaveBeenCalled();
      } );
    

    【讨论】:

    • 我认为您不需要spyOn( component, 'closeInfoLayer' );。我认为这主要用于检查外部服务的函数调用时,例如:spyOn(myService, 'aMethodThere');
    • 好吧,我需要 something 来再次测试。该方法中没有设置任何变量,唯一的结果是函数调用。所以这就是我测试的 - 它被称为。怎么办?
    • 如果你删除 spyOn( component, 'closeInfoLayer' ); 它应该可以工作,因为它会通过 if 语句,因为你模拟了事件。试一试,让我们知道
    • 那我应该怎么expect?只是删除spyOn 并离开expect 会抛出错误。
    • 你能把错误贴在这里吗?我认为如果它抛出错误,则意味着它没有通过 if 语句并且没有调用 closeInfoLayer
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-11
    • 2013-03-07
    • 1970-01-01
    • 2017-05-10
    • 1970-01-01
    相关资源
    最近更新 更多