web-dev-qa-db-fra.com

Angular 5 tests: comment obtenir une référence au composant enfant

J'essaie de tester l'interaction entre un composant hôte et un composant enfant dans une application Angular. Je ne sais pas comment obtenir une référence au composant enfant créé lors de la création du parent Voici la configuration:

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);
  });
});

Changer la valeur de model dans hostFixture.componentInstance _ ne change pas réellement la valeur d'entrée data de childFixture.componentInstance; C'est ainsi que j'ai compris qu'il y avait deux instances de composant enfant.

Ma question est simple. Comment obtenir que childFixture fasse référence à la fixture de composant trouvée dans le modèle HostComponent, au lieu d’une instance différente de celle que j’ai actuellement?

Les documents n'ont pas été utiles.

21
BeetleJuice

Comme expliqué dans le guide , une instance de composant hôte est créée avec TestBed.createComponent, et l’instance du composant enfant peut être sélectionnée parmi debugElement avec By helper :

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

Ou:

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

La réponse ci-dessus est bonne, répond à la question du corps, mais l'en-tête/titre de la question demande autre chose. Je voulais aussi répondre à la question posée par l'en-tête. La réponse d'Estus est correcte pour le cas d'utilisation spécifique, mais Google vous amène ici en fonction de la question dans le titre.

Pour obtenir le composant enfant et non l'élément natif:

Composant de test (appelé HostComponent dans la question): <child [data]="model" #child></child>

Puis dans la définition de classe:

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

Enfin, lors des tests, sur une spécification:

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

Vous pouvez utiliser cela dans un scénario de test, et c'est ce que je fais, pour trouver le composant enfant que vous essayez réellement de tester.


Le reste consiste à satisfaire un aspect discutable évoqué dans les commentaires.

Il y a également de bonnes raisons de rendre les choses privées lorsque cela est possible. Je ne suis pas sûr de ce que je ressens à ce sujet si vous voulez le tester à l'unité. Si vous souhaitez tester un membre privé, vous devez laisser le compilateur TypeScript que vous souhaitez insérer avec les membres privés accessible publiquement en le spécifiant et en le plaçant entre parenthèses pour qu'il soit clair.

Dans le composant:

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

Dans le test:

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

Parcourez les noeuds enfant des debugElement (s) et accédez à la propriété context pour avoir accès au composant et à ses propriétés

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

C'est une approche très statique car si un nouvel enfant est ajouté, vous accédez peut-être au mauvais ChildNode. Il est préférable d'écrire une méthode d'assistance qui traverse les noeuds enfant et trouve le bon nom.

0
troYman