programing

Angular2에서 이벤트 이미터를 테스트할 방법이 있습니까?

iphone6s 2023. 5. 12. 21:42
반응형

Angular2에서 이벤트 이미터를 테스트할 방법이 있습니까?

이벤트 이미터를 사용하는 구성 요소가 있으며 페이지의 다른 사용자가 클릭하면 이벤트 이미터가 사용됩니다.단위 테스트 중에 이벤트 이미터를 관찰하고 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');
});

가장 높은 투표를 받은 답변은 효과가 있지만, 좋은 테스트 관행을 보여주지 못하고 있기 때문에 몇 가지 실제 사례를 들어 귄터의 답변을 확대해 보려고 생각했습니다.

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

@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);
  • 의 이름@Input모래땅@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여기 테스트 호스트가 있으므로 실제로 테스트하는 구성 요소에 과도하게 연결되지 않았다고 확신할 수 있습니다.

이미터를 구독하거나 이미터에 바인딩할 수 있습니다.@Output()부모 템플릿에서 바인딩이 업데이트되었는지 확인합니다.클릭 이벤트를 발송한 후 구독이 실행될 수도 있습니다.

저는 방출된 배열의 길이를 테스트해야 하는 요구 사항이 있었습니다.이것이 바로 제가 다른 답변들 위에 올린 방법입니다.

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

테스트: @Output() 값 newEventEmitter();

HTML

<input [(ngModel)]="_myInputValue" class="my-input" (keyup)="value.emit($event.target.value)" />

스펙

it('should emit a value when user types input', () =>
{
  spyOn(component.value, 'emit');

  element.query(By.css('.my-input'))
  .triggerEventHandler('keyup', {target: {value: 'my input value'}});

  fixture.detectChanges();

  expect(component.value.emit).toHaveBeenCalled();
  expect(component.value.emit).toHaveBeenCalledWith('my input value');
}

참고: 트리거EventHandler()

  • 첫 번째 인수는 'keyup', 'keydown.enter', 'keyup.esc' 등을 사용할 수 있습니다.
  • 두 번째 인수는 $event 개체, 즉 HTML의 "$event.target.value"입니다.

언급URL : https://stackoverflow.com/questions/35319476/any-way-to-test-eventemitter-in-angular2

반응형