Angular 2 Karma Test 'nome-do-componente' não é um elemento conhecido

104

No AppComponent, estou usando o componente nav no código HTML. A interface do usuário parece boa. Sem erros ao fazer o serviço. e sem erros no console quando olho para o aplicativo.

Mas quando executei Karma para meu projeto, ocorreu um erro:

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.

Em meu app.module.ts :

Há sim:

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

Também está na parte de declarações do NgModule

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

Estou usando NavComponentno meuAppComponent

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>

Eu vi uma pergunta semelhante, mas a resposta nessa pergunta diz que devemos adicionar NgModule no componente de navegação que tem uma exportação nele, mas estou recebendo um erro de compilação quando faço isso.

Existe também: app.component.spec.ts

import {NavComponent} from './nav/nav.component';
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
Angela P
fonte
Você provavelmente está perdendo uma importação em seu arquivo de especificações. Estou assumindo que o teste de especificações está em app.spec.ts, então você vai querer import { NavComponent }em seu spec.ts
Z. Bagley
1
é importado. Estava faltando a parte da declaração
Ângela P
1
Importar e declarar o componente personalizado dentro de app.component.spec.ts funcionou para mim, obrigado pessoal!
ENDEESA

Respostas:

160

Como nos testes de unidade você deseja testar o componente principalmente isolado de outras partes do seu aplicativo, o Angular não adicionará as dependências do seu módulo, como componentes, serviços, etc. por padrão. Portanto, você precisa fazer isso manualmente em seus testes. Basicamente, você tem duas opções aqui:

A) Declare o NavComponent original no teste

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

B) Zombar do NavComponent

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

// it(...) test cases 

});

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

Você encontrará mais informações na documentação oficial .

Kim Kern
fonte
Obrigado ... Funcionou para mim !!
Hidayt Rahman de
1
Obrigado por isso. Eu tive o problema de ter que importar vários componentes e módulos a ponto de fazer muito mais sentido apenas importar AppModulena configuração do TestBed. Você recomendaria contra isso?
mcheah
@ Jonathan talvez o componente que você declarou tenha dependências próprias? Em um teste de unidade, é melhor usar simulações.
Kim Kern
8

Você também pode usar 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
fonte
3
existem problemas potenciais que irão surgir disso? Parece uma solução conveniente, mas existem erros importantes que serão anulados por isso?
mcheah
8
Isso é o que os documentos de teste dizem: "O NO_ERRORS_SCHEMA também evita que o compilador informe sobre os componentes e atributos ausentes que você omitiu inadvertidamente ou digitou incorretamente. Você pode perder horas perseguindo bugs fantasmas que o compilador teria detectado em um instante."
Kim Kern
5
você definitivamente não vai introduzir um comportamento implícito extra em seus testes de unidade: usar NO_ERRORS_SCHEMA irá encorajá-lo a colocar dependências na zona 'cinza' entre 'simulado' e 'puxado'. quaisquer alterações nessas dependências podem potencialmente desencadear a interrupção de testes de unidade aparentemente não relacionados - nada bom
averasko
0

Para mim, importar o componente no pai resolveu o problema.

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

Adicione isso spec of the parentonde este componente é usado.

Kailas
fonte
0

Mais um motivo é que pode haver vários .compileComponents()para beforeEach()em seu caso de teste

por exemplo

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

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

Etapa 1: Crie stubs no início do arquivo de especificação.

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

Etapa 2: adicionar stubs nas declarações do componente.

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