Saya memiliki komponen yang menggunakan EventEmitter dan EventEmitter digunakan ketika seseorang di halaman diklik. Apakah ada cara agar saya dapat mengamati EventEmitter selama pengujian unit, dan menggunakan TestComponentBuilder untuk mengklik elemen yang memicu metode EventEmitter.next () dan melihat apa yang dikirim?
unit-testing
angular
tallkid24
sumber
sumber
Jawaban:
Tes Anda bisa jadi:
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'); });
ketika komponen Anda adalah:
@Component({ ... }) class MyComponent { @Output myEventEmitter = new EventEmitter<string>(); buttonClick() { this.myEventEmitter.emit('hello'); } }
sumber
<my-component (myEventEmitter)="function($event)"></my-component>
dan dalam pengujian yang saya lakukan: tcb.overrideTemplate (TestComponent, html) .createAsync (TestComponent)Anda bisa menggunakan mata-mata, tergantung gaya Anda. Inilah cara Anda menggunakan mata-mata dengan mudah untuk melihat apakah
emit
sedang ditembakkan ...it('should emit on click', () => { spyOn(component.eventEmitter, 'emit'); component.buttonClick(); expect(component.eventEmitter.emit).toHaveBeenCalled(); expect(component.eventEmitter.emit).toHaveBeenCalledWith('bar'); });
sumber
expect
mata-mata yang sebenarnya (hasilspyOn()
panggilan)?Anda dapat berlangganan ke emitor atau mengikatnya, jika itu adalah
@Output()
, di template induk dan memeriksa di komponen induk apakah pengikatan telah diperbarui. Anda juga dapat mengirimkan peristiwa klik dan langganan harus diaktifkan.sumber
TestComponent
has<my-component (someEmitter)="value=$event">
(wheresomeEmitter
is an@Output()
) makavalue
properti dariTextComponent
harus diperbarui dengan event yang dikirim.Saya memiliki persyaratan untuk menguji panjang array yang dipancarkan. Jadi ini adalah bagaimana saya melakukan ini di atas Jawaban lainnya.
sumber
Meskipun jawaban pilihan tertinggi berfungsi, namun tidak menunjukkan praktik pengujian yang baik, jadi saya pikir saya akan memperluas jawaban Günter dengan beberapa contoh praktis.
Bayangkan kita memiliki komponen sederhana berikut:
@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!'); } }
Komponen adalah sistem yang diuji, memata-matai bagian-bagiannya yang merusak enkapsulasi. Tes komponen sudut seharusnya hanya mengetahui tiga hal:
fixture.nativeElement.querySelector
);@Input
s dan@Output
s; danApa pun yang melibatkan pemanggilan metode secara langsung pada instans atau memata-matai bagian komponen terlalu erat digabungkan dengan penerapan, dan akan menambah gesekan pada refactoring - uji ganda sebaiknya hanya digunakan untuk kolaborator. Dalam hal ini, karena kita tidak memiliki kolaborator, kita seharusnya tidak perlu setiap mengolok-olok, mata-mata atau ganda tes lainnya.
Salah satu cara untuk mengujinya adalah dengan berlangganan langsung ke emitor, lalu menjalankan tindakan klik (lihat Komponen dengan masukan dan keluaran ):
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!'); }); });
Meskipun ini berinteraksi langsung dengan instance komponen, nama dari
@Output
adalah bagian dari API publik, jadi tidak terlalu terkait erat.Atau, Anda dapat membuat host pengujian sederhana (lihat Komponen di dalam host pengujian ) dan benar-benar memasang komponen Anda:
@Component({ selector: 'test-host', template: ` <my-demo (clicked)="onClicked($event)"></my-demo> ` }) class TestHostComponent { lastClick = ''; onClicked(value: string): void { this.lastClick = value; } }
kemudian uji komponen dalam konteks:
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!'); }); });
Ini
componentInstance
adalah host pengujian , jadi kami dapat yakin bahwa kami tidak terlalu digabungkan dengan komponen yang sebenarnya kami uji.sumber