Angular 5 テスト: @ViewChild、TestBed.createComponent、ComponentTestInstance - 子コンポーネントへの参照取得方法
Angular 5 テスト: 子コンポーネントへの参照を取得する方法
ここでは、Angular 5 で子コンポーネントへの参照を取得するためのいくつかの方法について説明します。
@ViewChildデコレータ
@ViewChild
デコレータは、テンプレート内で定義された子コンポーネントインスタンスへの参照を取得するために使用されます。
@Component({
selector: 'app-parent',
template: `
<child-component #child></child-component>
`,
})
export class ParentComponent {
@ViewChild('child') child: ChildComponent;
ngOnInit() {
// 子コンポーネントのプロパティにアクセス
console.log(this.child.name);
// 子コンポーネントのメソッドを呼び出す
this.child.greet();
}
}
この例では、@ViewChild
デコレータを使用して child
という名前のテンプレート変数に関連付けられた ChildComponent
インスタンスへの参照を取得しています。ngOnInit
メソッド内で、この参照を使用して子コンポーネントのプロパティ name
にアクセスし、メソッド greet()
を呼び出しています。
TestBed.createComponent
TestBed.createComponent
メソッドは、テスト対象のコンポーネントを作成し、そのコンポーネントのインスタンスと子コンポーネントへの参照を取得するために使用されます。
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { ChildComponent } from './child.component';
describe('ParentComponent', () => {
let fixture: ComponentFixture<ParentComponent>;
let parentComponent: ParentComponent;
beforeEach(() => {
fixture = TestBed.createComponent(ParentComponent);
parentComponent = fixture.componentInstance;
});
it('should get reference to child component', () => {
const childComponent = fixture.debugElement.query(child => child.componentInstance instanceof ChildComponent);
expect(childComponent).toBeTruthy();
});
});
この例では、TestBed.createComponent
メソッドを使用して ParentComponent
インスタンスを作成しています。次に、fixture.debugElement.query
メソッドを使用して、ChildComponent
インスタンスへの参照を取得しています。
ComponentTestInstance
ComponentTestInstance
インターフェースは、テスト対象のコンポーネントインスタンスへのアクセスを提供します。
import { ComponentTestInstance } from '@angular/core/testing';
import { ChildComponent } from './child.component';
describe('ParentComponent', () => {
let fixture: ComponentFixture<ParentComponent>;
let parentComponent: ParentComponent;
beforeEach(() => {
fixture = TestBed.createComponent(ParentComponent);
parentComponent = fixture.componentInstance;
});
it('should get reference to child component using ComponentTestInstance', () => {
const childComponent = fixture.debugElement.componentInstance as ComponentTestInstance<ChildComponent>;
expect(childComponent).toBeTruthy();
});
});
この例では、ComponentTestInstance
インターフェースを使用して ChildComponent
インスタンスへの参照を取得しています。
これらの方法は、Angular 5 テストで子コンポーネントへの参照を取得するために使用できます。どの方法を使用するかは、テストのニーズによって異なります。
fixture.detectChanges
メソッドを呼び出すことで、子コンポーネントのプロパティやメソッドへの変更を反映させることができます。fixture.debugElement.queryAll
メソッドを使用して、テンプレート内に存在するすべての子コンポーネントインスタンスへの参照を取得できます。
親コンポーネント (app-parent.component.ts)
import { Component, OnInit } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'app-parent',
template: `
<child-component #child></child-component>
<button (click)="greetChild()">子コンポーネントに挨拶</button>
`,
})
export class ParentComponent implements OnInit {
@ViewChild('child') child: ChildComponent;
ngOnInit() {
console.log('親コンポーネントが初期化されました。');
}
greetChild() {
this.child.greet();
}
}
子コンポーネント (child.component.ts)
import { Component, Input } from '@angular/core';
@Component({
selector: 'child-component',
template: `
<p>名前: {{ name }}</p>
<button (click)="greet()">挨拶</button>
`,
})
export class ChildComponent {
@Input() name = '子コンポーネント';
greet() {
console.log('子コンポーネントから挨拶します!');
}
}
app.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ChildComponent } from './child.component';
describe('AppComponent', () => {
let fixture: ComponentFixture<AppComponent>;
let app: AppComponent;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AppComponent, ChildComponent],
imports: [AppRoutingModule],
}).compileComponents();
fixture = TestBed.createComponent(AppComponent);
app = fixture.componentInstance;
});
it('should create the app', () => {
expect(app).toBeTruthy();
});
it('should get reference to child component and call greet method', () => {
const childComponent = fixture.debugElement.query(child => child.componentInstance instanceof ChildComponent);
const spy = spyOn(childComponent.componentInstance, 'greet');
app.greetChild();
fixture.detectChanges();
expect(spy).toHaveBeenCalled();
});
});
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ChildComponent } from './child.component';
describe('AppComponent', () => {
let fixture: ComponentFixture<AppComponent>;
let app: AppComponent;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AppComponent, ChildComponent],
imports: [AppRoutingModule],
}).compileComponents();
fixture = TestBed.createComponent(AppComponent);
app = fixture.componentInstance;
});
it('should create the app', () => {
expect(app).toBeTruthy();
});
it('should get reference to child component using TestBed.createComponent', () => {
const childFixture = TestBed.createComponent(ChildComponent);
const childComponent = childFixture.componentInstance;
expect(childComponent).toBeTruthy();
});
});
この例では、TestBed.createComponent
メソッドを使用して ChildComponent
インスタンスを作成しています。
サービスを使用して、親コンポーネントと子コンポーネント間でデータを共有できます。このデータには、子コンポーネントへの参照を含めることもできます。
import { Component, OnInit } from '@angular/core';
import { ChildComponent } from './child.component';
import { MyService } from './my.service';
@Component({
selector: 'app-parent',
template: `
<child-component [childInput]="child"></child-component>
`,
})
export class ParentComponent implements OnInit {
child: ChildComponent;
constructor(private myService: MyService) {}
ngOnInit() {
this.child = new ChildComponent();
this.myService.setChildComponent(this.child);
}
}
import { Component, Input } from '@angular/core';
import { MyService } from './my.service';
@Component({
selector: 'child-component',
template: `
<p>名前: {{ name }}</p>
`,
})
export class ChildComponent {
@Input() name = '子コンポーネント';
constructor(private myService: MyService) {}
ngOnInit() {
this.myService.getChildComponent().greet();
}
}
my.service.ts
import { Injectable } from '@angular/core';
import { ChildComponent } from './child.component';
@Injectable({
providedIn: 'root',
})
export class MyService {
private childComponent: ChildComponent;
setChildComponent(childComponent: ChildComponent) {
this.childComponent = childComponent;
}
getChildComponent(): ChildComponent {
return this.childComponent;
}
}
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ChildComponent } from './child.component';
import { MyService } from './my.service';
describe('AppComponent', () => {
let fixture: ComponentFixture<AppComponent>;
let app: AppComponent;
let myService: MyService;
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [AppComponent, ChildComponent],
imports: [AppRoutingModule],
providers: [MyService],
}).compileComponents();
fixture = TestBed.createComponent(AppComponent);
app = fixture.componentInstance;
myService = TestBed.inject(MyService);
});
it('should create the app', () => {
expect(app).toBeTruthy();
});
it('should get reference to child component using service', () => {
const childComponent = myService.getChildComponent();
expect(childComponent).toBeTruthy();
});
});
この例では、MyService
サービスを使用して、親コンポーネントと子コンポーネント間で ChildComponent
インスタンスへの参照を共有しています。
イベントを使用する
イベントを使用して、親コンポーネントと子コンポーネント間で通信できます。この通信を使用して、子コンポーネントから自身への参照を親コンポーネントに渡すことができます。
import { Component, OnInit } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'app-parent',
template: `
<child-component (childEvent)="onChildEvent($event)"></child-component>
`,
})
export class ParentComponent implements OnInit {
childComponentReference: ChildComponent;
onChildEvent(childComponent: ChildComponent) {
this.childComponentReference = childComponent;
}
}
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'child-component
angular unit-testing