如何测试 Jasmine、Angular 中的声明[] 中从子级发送到父级的事件

问题描述 投票:0回答:1

我有一个很大的 .spec 文件,用作(我们称之为)MainComponent 的集成测试。声明包含多个子组件及其子组件。我关心两个使用 EventEmitter 进行通信的组件。当用户单击 ChildComponent 中的按钮时,事件将被发出并触发 ParentComponent 中的函数。

我试图模拟 ParentComponent 但当测试执行时,它会沿着 ParentComponent 的默认路径走。

我无法显示整个文件,但这就是规范的作用:

describe('main component Spec', () => {
    let fixture: ComponentFixture<MainComponent>;

    let mainComponent: MainComponent;

    const parentComponentSpyObj = jasmine.createSpyObj('ParentComponent', ['onEventReceived']);

    beforeEach(waitForAsync(() => {
        TestBed.configureTestingModule({
            declarations: [
                ParentComponent,
                ChildComponent
            ],
            schemas: [CUSTOM_ELEMENTS_SCHEMA],
            imports: [FlexLayoutModule],
            providers: [
                { provide: ParentComponent, useValue: parentComponentSpyObj },
            ]
        }).compileComponents();
    }));

    beforeEach(() => {
        fixture = TestBed.createComponent(MainComponent);
        mainComponent = fixture.componentInstance;
        fixture.detectChanges();
    });

    it(`Should call onEventReceived of ParentComponent when child button is pressed`, () => {
        // Given
        const childComponentButton = fixture.debugElement.nativeElement.querySelector('#button');

        // When
        childComponentButton.click();
        fixture.detectChanges();

        // Then
        expect(parentComponentSpyObj.onEventReceived).toHaveBeenCalledTimes(1);
    });

});

测试失败,并显示消息 - Expected ParentComponentSpyObj.onEventReceived to have been called once。被调用了 0 次。

angular testing jasmine parent-child eventemitter
1个回答
0
投票

问题在于提供的模拟对象未正确注入到组件层次结构中。您需要以替换实际对象的方式提供模拟对象

ParentComponent

import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

// Import the components and any other required modules

describe('main component Spec', () => {
  let fixture: ComponentFixture<MainComponent>;
  let mainComponent: MainComponent;

  // Create a spy object for ParentComponent
  const parentComponentSpyObj = jasmine.createSpyObj('ParentComponent', ['onEventReceived']);

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      declarations: [MainComponent, ParentComponent, ChildComponent],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      imports: [FlexLayoutModule],
      providers: [
        // Provide the spy object for ParentComponent
        { provide: ParentComponent, useClass: parentComponentSpyObj },
      ],
    }).compileComponents();
  });

  beforeEach(() => {
    fixture = TestBed.createComponent(MainComponent);
    mainComponent = fixture.componentInstance;
    fixture.detectChanges();
  });

  it(`Should call onEventReceived of ParentComponent when child button is pressed`, () => {
    // Given
    const childComponent: ChildComponent = fixture.debugElement.query(By.directive(ChildComponent)).componentInstance;
    const childComponentButton = fixture.debugElement.query(By.css('#button'));

    // When
    childComponentButton.triggerEventHandler('click', null);
    fixture.detectChanges();

    // Then
    expect(parentComponentSpyObj.onEventReceived).toHaveBeenCalledTimes(1);
  });
});

© www.soinside.com 2019 - 2024. All rights reserved.