25 votes

Angular testing Impossible de lire la propriété 'name' d'undefined

J'ai un ModalComponent qui accepte certaines propriétés du parent via @Input.

C'est ce qui cause le problème des tests

Erreur de type : Impossible de lire la propriété 'name' d'undefined.

Le nom est utilisé dans ngOnInit et devrait venir de @Input displayeddata .

Comment puis-je le passer dans mon test unitaire ?

Actuellement, mon test ressemble à ceci

beforeEach(async(() => {
        TestBed.configureTestingModule({
            declarations: [ModalComponent, FilterComponent],
            imports: [ReactiveFormsModule, TranslateModule]
        })
            .compileComponents();
    }));

    beforeEach(async () => {
    fixture = TestBed.createComponent(ModalComponent);
    component = fixture.componentInstance;
    component.displayeddata = {
        name: 'One component',
        caption: 'Caption',
        componentName: 'TextareaComponent'
    };
    fixture.detectChanges();
});

it('should create', async () => {
    fixture.detectChanges();
    fixture.whenStable().then(() => {
        expect(component).toBeTruthy();
    });
});

C'est le seul test pour mon composant et il échoue.

Mise à jour n° 1

Voici ce que j'obtiens sur console.log(this.displayeddata);

Object
caption: "Caption"
component: "TextareaComponent"
name: "One component"

J'ai également modifié un peu mon code (code mis à jour) et j'obtiens maintenant une nouvelle erreur TypeError: Cannot read property 'caption' of undefined

Mise à jour n°2

modal.component.ts

export class ModalComponent implements OnInit {
@Input() showenpunctsnow;
@Input() displayeddata;
@Output() ComponentParametrsInputs: FormGroup = this.fb.group({
        name: ['', Validators.required],
        caption: ['', Validators.required],
        component: ['']
    });
constructor(private fb: FormBuilder) {}
ngOnInit() {

        console.log(this.displayeddata);

        this.ComponentParametrsInputs = this.fb.group({
            name: [this.displayeddata.name, Validators.required],
            caption: [this.displayeddata.caption, Validators.required],
            component: [this.displayeddata.componentName]
        });
    }

32voto

SirajB Points 185

Je vais juste commenter ici, même si le problème a déjà été résolu, au cas où quelqu'un d'autre rencontrerait le même problème.

Le problème provient très probablement du fichier html plutôt que du test unitaire ou du composant lui-même.

Dans votre fichier html :

  • Allez à l'endroit où vous utilisez {variable}.name
  • dans la section respective, div, ou ajouter autrement *ngIf="{variable}"

Il faut d'abord vérifier si cette variable existe. Ensuite, dans vos tests unitaires, faites simplement :

it('should create', ()=> {
   expect(component).toBeTruthy();
}

Si vous voulez ensuite vérifier si le composant se chargera avec une valeur spécifiée name :

it('should create with specified name', () => {
   component.{variable}.name = 'Foo'

   fixture.detectChanges();
   expect(fixture.debugElement.nativeElement.innerHTML)
    .toContain(component.{variable}.name)
}

5voto

dmcgrandle Points 3464

Je mets cette mise à jour en tant que "réponse" car elle ne tient pas dans un commentaire :)

Merci d'avoir publié la logique des composants. Avec ces informations, j'en ai eu assez pour mettre en place un environnement de test rapide ici : https://stackblitz.com/edit/stackoverflow-q-53086352?file=app%2Fmy.component.spec.ts

J'ai dû m'écarter légèrement de votre code ci-dessus de la manière suivante :

  • Le FilterComponent et le TranslateModule sont commentés car je n'ai pas accès à ce code et vous ne les testez pas à ce stade.
  • Vous n'avez pas utilisé "async" correctement dans la deuxième fonction "beforeEach" ainsi que dans la spécification "it" - vous n'avez pas enveloppé la fonction flèche dans un async, vous avez utilisé le mot réservé async pour définir la fonction comme asynchrone - une partie de async/await, qui est une chose totalement différente. Vous avez besoin d'une autre série de parenthèses après le mot async pour l'appeler comme la fonction angular/core/testing et non comme le mot réservé javascript :)
  • J'ai ajouté un modèle simple qui affiche une des variables displaydata

Cependant, ce qui est surprenant, c'est que lorsque j'ai mis votre code dans stackblitz, tout fonctionne parfaitement ! Il est donc clair que le problème que vous rencontrez est causé par un code qui est en dehors de ce que vous avez présenté jusqu'à présent.

Ma suggestion pour les prochaines étapes :

  • Vous pouvez soit modifier le stackblitz existant que j'ai créé, soit le transférer sur votre propre compte pour jouer avec.
  • ajouter du code/données supplémentaires jusqu'à ce que le problème se reproduise. Cela permettra de déterminer où se trouve l'erreur réelle.

Bonne chance !

1voto

Enima Points 113

Votre approche est bonne, je pense qu'elle échoue à cause de l'asynchronisme. Essayez ceci :

it('should create', () => {
    component.displayeddata = {
        name: 'One component',
        caption: 'Caption',
        component: 'TextareaComponent'
    };
    fixture.detectChanges();
    expect(component).toBeTruthy();
});

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X