web-dev-qa-db-ja.com

Angular 5テスト:子コンポーネントへの参照を取得する方法

Angularアプリケーションでホストコンポーネントと子コンポーネント間の相互作用をテストしようとしています。親が作成されたときに作成された子コンポーネントへの参照を取得する方法がわかりません。セットアップは次のとおりです。

child.component.spec.ts

@Component({template: `<child [data]="model"></child>`})
class HostComponent {
  public model:any;
}

describe('ChildComponent', () => {
  let hostFixture: ComponentFixture<HostComponent>;
  let childFixture: ComponentFixture<ChildComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ChildComponent, HostComponent]
    });
  }));

  beforeEach(() => {
    // this creates the child component as well, but how to get to it?
    hostFixture = TestBed.createComponent(HostComponent);

    // this creates a NEW instance of child component, not the one from the Host template
    // so it's not the instance I actually want to test
    childFixture = TestBed.createComponent(ChildComponent);
  });
});

hostFixture.componentInstancemodel値を変更しても、実際にはchildFixture.componentInstancedata入力値は変更されません。これが、子コンポーネントのインスタンスが2つあることを認識した方法です。

私の質問は簡単です。どのようにしてchildFixtureを取得して、現在ある別のインスタンスではなく、HostComponentテンプレートにあるコンポーネントフィクスチャを参照できますか?

ドキュメント 役に立たなかった。

21
BeetleJuice

ガイド で説明されているように、ホストコンポーネントインスタンスはTestBed.createComponent、および子コンポーネントのインスタンスは、 debugElement helperByから選択できます。

childDebugElement = hostFixture.debugElement.query(By.directive(ChildComponent));

または:

childDebugElement = hostFixture.debugElement.query(By.css('child'));
43
Estus Flask

上記の答えは良いです、本文の質問に答えますが、質問のヘッダー/タイトルは何か他のものを尋ねます。ヘッダーによって提起された質問にも答えたいと思いました。 Estusの回答は特定のユースケースに適していますが、タイトルの質問に基づいてGoogleがここに表示します。

ネイティブ要素ではなく子コンポーネントを取得するには:

テストコンポーネント(質問ではHostComponentと呼ばれます):<child [data]="model" #child></child>

次に、クラス定義で:

@Component({template: `<child #child [data]="model"></child>`})
class HostComponent {
    public model:any;
    @ViewChild('child') child;
}

最後に、テスト時に、仕様について:

it('should do something', () => {
    component.child.value
    component.child.method
    // etc.
}

テストケースでこれを使用することもできますが、実際にテストしようとしている子コンポーネントを見つけるために使用します。


残りは、コメントで提起された議論の余地のある側面を満たすことです。

可能であれば、物事をプライベートにするという強力なケースもあります。あなたがそれを単体テストしたい場合、私はそれについてどう思うかわかりません。プライベートメンバーをテストする場合は、キャストする対象を明確にするために、キャストしてかっこで囲むことにより、プライベートメンバーを持つオブジェクトがパブリックにアクセスできるようにするTypeScriptコンパイラーを許可する必要があります。

コンポーネント内:

...
    @ViewChild('child') private child;
...

テストでは:

...
    (<any>component).child.value
    (<any>component).child.method
...
4
Steven Lacks

DebugElement(s)のchildNodesを反復処理し、コンテキストプロパティにアクセスして、コンポーネントとそのプロパティにアクセスします。

let debugElement = hostFixture.debugElement.childNodes[x] as DebugElement
debugElement = debugElement.childNodes[x] as DebugElement
...
let component = debugElement.context as YourComponent

新しい子が追加された場合、間違ったchildNodeにアクセスする可能性があるため、これは非常に静的なアプローチです。 childNodesを通過して正しい名前を見つけるヘルパーメソッドを記述する方が適切です。

0
troYman