[unit-testing] Angular2에서 EventEmitter를 테스트하는 방법이 있습니까?

EventEmitter를 사용하는 구성 요소가 있고 EventEmitter는 페이지의 누군가를 클릭 할 때 사용됩니다. 단위 테스트 중에 EventEmitter를 관찰하고 TestComponentBuilder를 사용하여 EventEmitter.next () 메서드를 트리거하는 요소를 클릭하고 전송 된 내용을 볼 수있는 방법이 있습니까?



답변

테스트는 다음과 같습니다.

it('should emit on click', () => {
   const fixture = TestBed.createComponent(MyComponent);
   // spy on event emitter
   const component = fixture.componentInstance;
   spyOn(component.myEventEmitter, 'emit');

   // trigger the click
   const nativeElement = fixture.nativeElement;
   const button = nativeElement.querySelector('button');
   button.dispatchEvent(new Event('click'));

   fixture.detectChanges();

   expect(component.myEventEmitter.emit).toHaveBeenCalledWith('hello');
});

구성 요소가 다음과 같은 경우

@Component({ ... })
class MyComponent {
  @Output myEventEmitter = new EventEmitter<string>();

  buttonClick() {
    this.myEventEmitter.emit('hello');
  }
}


답변

스타일에 따라 스파이를 사용할 수 있습니다. 스파이를 사용하여 쉽게 emit해고 되는지 확인하는 방법은 다음과 같습니다 .

it('should emit on click', () => {
    spyOn(component.eventEmitter, 'emit');
    component.buttonClick();
    expect(component.eventEmitter.emit).toHaveBeenCalled();
    expect(component.eventEmitter.emit).toHaveBeenCalledWith('bar');
});


답변

에미 터를 구독하거나 @Output()부모 템플릿에서 이미 터에 바인딩 할 수 있으며 바인딩이 업데이트 된 경우 부모 구성 요소를 체크인 할 수 있습니다. 클릭 이벤트를 전달하면 구독이 시작됩니다.


답변

방출 된 배열의 길이를 테스트해야했습니다. 그래서 이것이 다른 Answers 위에 이것을 한 방법입니다.

expect(component.myEmitter.emit).toHaveBeenCalledWith([anything(), anything()]);


답변

가장 많이 득표 한 답변이 작동하지만 좋은 테스트 관행을 보여주지 않으므로 몇 가지 실용적인 예를 통해 Günter의 답변 을 확장 할 것이라고 생각했습니다 .

다음과 같은 간단한 구성 요소가 있다고 가정 해 보겠습니다.

@Component({
  selector: 'my-demo',
  template: `
    <button (click)="buttonClicked()">Click Me!</button>
  `
})
export class DemoComponent {
  @Output() clicked = new EventEmitter<string>();

  constructor() { }

  buttonClicked(): void {
    this.clicked.emit('clicked!');
  }
}

구성 요소는 테스트중인 시스템이며 일부를 감시하면 캡슐화가 중단됩니다. 각도 구성 요소 테스트는 다음 세 가지만 알아야합니다.

  • DOM (예 :를 통해 액세스 fixture.nativeElement.querySelector)
  • @Inputs 및 @Outputs 의 이름 ; 과
  • 협업 서비스 (DI 시스템을 통해 주입 됨).

인스턴스에서 직접 메서드를 호출하거나 구성 요소의 일부를 감시하는 것과 관련된 모든 것은 구현과 너무 밀접하게 연결되어 리팩토링에 마찰을 추가합니다. 테스트 이중은 공동 작업자에게만 사용해야합니다. 이 경우에는 공동 작업자가 없으므로 모의, 스파이 또는 기타 테스트 복식이 필요 하지 않습니다 .


이를 테스트하는 한 가지 방법은 이미 터를 직접 구독 한 다음 클릭 작업을 호출하는 것 입니다 (입력 및 출력이있는 구성 요소 참조 ).

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ DemoComponent ]
    })
    .compileComponents();
  }));

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

  it('should emit when clicked', () => {
    let emitted: string;
    component.clicked.subscribe((event: string) => {
      emitted = event;
    });

    fixture.nativeElement.querySelector('button').click();

    expect(emitted).toBe('clicked!');
  });
});

이는 구성 요소 인스턴스와 직접 상호 작용하지만의 이름은 @Output공용 API의 일부이므로 너무 밀접하게 결합되어 있지 않습니다.


또는 간단한 테스트 호스트를 만들고 (테스트 호스트 내부의 구성 요소 참조 ) 실제로 구성 요소를 마운트 할 수 있습니다.

@Component({
  selector: 'test-host',
  template: `
    <my-demo (clicked)="onClicked($event)"></my-demo>
  `
})
class TestHostComponent {
  lastClick = '';

  onClicked(value: string): void {
    this.lastClick = value;
  }
}

그런 다음 컨텍스트에서 구성 요소를 테스트합니다.

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ TestHostComponent, DemoComponent ]
    })
    .compileComponents();
  }));

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

  it('should emit when clicked', () => {
    fixture.nativeElement.querySelector('button').click();

    expect(component.lastClick).toBe('clicked!');
  });
});

componentInstance여기입니다 테스트 호스트 우리가 너무 우리가 실제로 테스트하고 구성 요소에 연결하지 않을 확신 할 수 있습니다.


답변