Angular 2 Karma Test 'nom-composant' n'est pas un élément connu

105

Dans AppComponent, j'utilise le composant nav dans le code HTML. L'interface utilisateur a l'air bien. Aucune erreur lors du service ng. et aucune erreur dans la console lorsque je regarde l'application.

Mais lorsque j'ai exécuté Karma pour mon projet, il y a une erreur:

Failed: Template parse errors: 
'app-nav' is not a known element:
1. If 'app-nav' is an Angular component, then verify that it is part of this module.
2. If 'app-nav' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.

Dans mon app.module.ts :

il y a:

import { NavComponent } from './nav/nav.component';

C'est aussi dans la partie déclarations de NgModule

@NgModule({
  declarations: [
    AppComponent,
    CafeComponent,
    ModalComponent,
    NavComponent,
    NewsFeedComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    JsonpModule,
    ModalModule.forRoot(),
    ModalModule,
    NgbModule.forRoot(),
    BootstrapModalModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

J'utilise le NavComponentdans monAppComponent

app.component.ts

import { Component, ViewContainerRef } from '@angular/core';
import { Overlay } from 'angular2-modal';
import { Modal } from 'angular2-modal/plugins/bootstrap';
import { NavComponent } from './nav/nav.component';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Angela';
}

app.component.html

<app-nav></app-nav>
<div class="container-fluid">
</div>

J'ai vu une question similaire, mais la réponse à cette question dit que nous devrions ajouter NgModule dans le composant nav qui contient une exportation, mais j'obtiens une erreur de compilation lorsque je fais cela.

Il existe également: app.component.spec.ts

import {NavComponent} from './nav/nav.component';
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
Angela P
la source
Il vous manque probablement une importation dans votre fichier de spécifications. Je suppose que le test de spécification est sur app.spec.ts, donc vous voudrez import { NavComponent }dans vos spécifications.ts
Z. Bagley
1
il est importé. Je manquais la partie déclaration
Angela P
1
L'importation et la déclaration du composant personnalisé dans app.component.spec.ts ont fonctionné pour moi, merci les gars!
ENDEESA

Réponses:

162

Parce que dans les tests unitaires, vous souhaitez tester le composant principalement isolé des autres parties de votre application, Angular n'ajoutera pas les dépendances de votre module telles que les composants, les services, etc. par défaut. Vous devez donc le faire manuellement dans vos tests. En gros, vous avez deux options ici:

A) Déclarez le NavComponent d'origine dans le test

describe('AppComponent', () => {
  beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [
          AppComponent,
          NavComponent
        ]
      }).compileComponents();
    }));

B) Simulez le NavComponent

describe('AppComponent', () => {
  beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [
          AppComponent,
          MockNavComponent
        ]
      }).compileComponents();
    }));

// it(...) test cases 

});

@Component({
  selector: 'app-nav',
  template: ''
})
class MockNavComponent {
}

Vous trouverez plus d'informations dans la documentation officielle .

Kim Kern
la source
Merci ... A travaillé pour moi !!
Hidayt Rahman
1
Merci pour cela. J'ai rencontré le problème de devoir importer plusieurs composants et modules au point où il est beaucoup plus logique de simplement importer le AppModuledans la configuration TestBed. Recommanderiez-vous contre cela?
mcheah
@jonathan peut-être que le composant que vous avez déclaré a ses propres dépendances? Dans un test unitaire, il est préférable d'utiliser des simulations.
Kim Kern
8

Vous pouvez aussi utiliser NO_ERRORS_SCHEMA

describe('AppComponent', () => {
beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [
      AppComponent
    ],
    schemas: [NO_ERRORS_SCHEMA]
  }).compileComponents();
}));

https://2018.ng-conf.org/mocking-dependencies-angular/

Adrian
la source
3
y a-t-il des problèmes potentiels qui en découleront? Cela semble être une solution pratique, mais y a-t-il des erreurs importantes qui seront annulées par cela?
mcheah
8
Voici ce que disent les documents de test : "Le NO_ERRORS_SCHEMA empêche également le compilateur de vous informer des composants manquants et des attributs que vous avez omis par inadvertance ou mal orthographiés. Vous pourriez perdre des heures à rechercher des bogues fantômes que le compilateur aurait détectés en un instant."
Kim Kern
5
vous n'aurez certainement pas l'habitude d'introduire un comportement implicite supplémentaire dans vos tests unitaires: l'utilisation de NO_ERRORS_SCHEMA vous encouragera à placer les dépendances dans la zone «grise» entre «mocked» et «pull in». toute modification de ces dépendances peut potentiellement déclencher la rupture de tests unitaires apparemment sans rapport - pas bon
averasko
0

Pour moi, l'importation du composant dans le parent a résolu le problème.

describe('AppComponent', () => {
  beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [
          AppComponent,
          NavComponent
        ]
      }).compileComponents();
    }));

Ajoutez-le là spec of the parentoù ce composant est utilisé.

Kailas
la source
0

Une autre raison est qu'il peut y avoir plusieurs .compileComponents()pour beforeEach()dans votre cas de test

par exemple

beforeEach(async(() => {
  TestBed.configureTestingModule({
    declarations: [TestComponent]
  }).compileComponents();
}));

beforeEach(() => {
  TestBed.configureTestingModule({
    imports: [HttpClientModule],
    declarations: [Test1Component],
    providers: [HttpErrorHandlerService]
  }).compileComponents();
});
Devaarth
la source
0

Étape 1: Créez des stubs au début du fichier de spécifications.

@Component({selector: 'app-nav', template: ''})
class NavComponent{}

Étape 2: ajoutez des stubs dans les déclarations des composants.

TestBed.configureTestingModule({
  imports: [
    RouterTestingModule
  ],
  declarations: [
    AppComponent,
    NavComponent
  ],
}).compileComponents();
Yuvraj Patil
la source