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
) @Input
s 및@Output
s 의 이름 ; 과- 협업 서비스 (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
여기입니다 테스트 호스트 우리가 너무 우리가 실제로 테스트하고 구성 요소에 연결하지 않을 확신 할 수 있습니다.