ฉันมีส่วนประกอบที่ใช้ EventEmitter และ EventEmitter ถูกใช้เมื่อมีคนคลิกในเพจ มีวิธีใดบ้างที่ฉันสามารถสังเกต EventEmitter ระหว่างการทดสอบหน่วยและใช้ TestComponentBuilder เพื่อคลิกองค์ประกอบที่ทริกเกอร์เมธอด EventEmitter.next () และดูสิ่งที่ส่ง
ฉันมีส่วนประกอบที่ใช้ 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');
}
}
<my-component (myEventEmitter)="function($event)"></my-component>
และในการทดสอบฉันทำ: tcb.overrideTemplate (TestComponent, html) .createAsync (TestComponent)
คุณสามารถใช้สายลับได้ขึ้นอยู่กับสไตล์ของคุณ นี่คือวิธีที่คุณจะใช้สายลับได้อย่างง่ายดายเพื่อดูว่าemit
ถูกไล่ออกหรือไม่ ...
it('should emit on click', () => {
spyOn(component.eventEmitter, 'emit');
component.buttonClick();
expect(component.eventEmitter.emit).toHaveBeenCalled();
expect(component.eventEmitter.emit).toHaveBeenCalledWith('bar');
});
expect
เป็นสายลับที่แท้จริง (ผลจากการspyOn()
โทร) ไม่ใช่หรือ?
คุณสามารถสมัครใช้งานตัวปล่อยหรือเชื่อมโยงได้หากเป็น@Output()
แม่แบบในแม่แบบหลักและตรวจสอบในองค์ประกอบหลักว่ามีการอัปเดตการเชื่อมโยงหรือไม่ คุณยังสามารถจัดส่งเหตุการณ์การคลิกจากนั้นการสมัครใช้งานจะเริ่มทำงาน
TestComponent
has <my-component (someEmitter)="value=$event">
(โดยที่someEmitter
เป็น@Output()
) ดังนั้นvalue
คุณสมบัติของTextComponent
ควรจะถูกอัพเดตด้วยเหตุการณ์ที่ส่ง
ฉันมีความต้องการที่จะทดสอบความยาวของอาร์เรย์ที่ปล่อยออกมา นี่คือวิธีที่ฉันทำกับคำตอบอื่น ๆ
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!');
}
}
ส่วนประกอบคือระบบที่อยู่ระหว่างการทดสอบการสอดแนมบางส่วนของมันทำให้การห่อหุ้มแตก การทดสอบส่วนประกอบเชิงมุมควรรู้สามสิ่งเท่านั้น:
fixture.nativeElement.querySelector
);@Input
s และ@Output
s; และสิ่งใดก็ตามที่เกี่ยวข้องกับการเรียกใช้วิธีการโดยตรงบนอินสแตนซ์หรือการสอดแนมในส่วนต่างๆของส่วนประกอบนั้นเชื่อมโยงกับการนำไปใช้งานมากเกินไปและจะเพิ่มแรงเสียดทานให้กับการปรับโครงสร้างใหม่ - ควรใช้การทดสอบสองเท่าสำหรับผู้ทำงานร่วมกันเท่านั้น ในกรณีนี้เนื่องจากเราไม่มีผู้ทำงานร่วมกันเราจึงไม่จำเป็นต้องมีการล้อเลียนสายลับหรือคู่ทดสอบอื่น ๆ
วิธีหนึ่งในการทดสอบสิ่งนี้คือสมัครสมาชิกโดยตรงกับตัวปล่อยจากนั้นเรียกใช้การดำเนินการคลิก (ดูส่วนประกอบที่มีอินพุตและเอาต์พุต ):
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
นี่เป็นเจ้าภาพการทดสอบเพื่อให้เราสามารถมีความมั่นใจเราไม่ได้คู่สุดเหวี่ยงไปยังส่วนที่เรากำลังทดสอบจริง