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
持っている<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!');
}
}
コンポーネントはテスト中のシステムであり、その一部をスパイするとカプセル化が破られます。Angularコンポーネントのテストでは、次の3つのことだけを知っておく必要があります。
fixture.nativeElement.querySelector
);@Input
sと@Output
sの名前。そしてインスタンスでメソッドを直接呼び出したり、コンポーネントの一部をスパイしたりすることは、実装と密接に関連しているため、リファクタリングに摩擦が加わります。テストダブルは共同作業者にのみ使用する必要があります。この場合、共同編集者がいないため、モック、スパイ、その他のテストダブルは必要ありません。
これをテストする1つの方法は、エミッターに直接サブスクライブしてから、クリックアクションを呼び出すことです(入力と出力のあるコンポーネントを参照)。
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
ここで、テストホスト我々は過度に私たちが実際にテストしているコンポーネントに結合されていない確信することができて、。