Angular Karma Jasmine Błąd: Nielegalny stan: nie można załadować podsumowania dyrektywy

104

Zajmuję się repozytorium GitHub (z kątowym 7 i kątowego-CLI) i mam kilka testów z Karma i Jasmine pracuje w gałęzi master.

Teraz próbuję dodać funkcję leniwego ładowania, chodzi o to, że testy, które wcześniej przeszły, teraz nie. To zabawne, bo tylko testy z modułu leniwego ładowania kończą się niepowodzeniem ...

Oto kod i błąd:

import {async, TestBed} from '@angular/core/testing';
import {APP_BASE_HREF} from '@angular/common';
import {AppModule} from '../../app.module';
import {HeroDetailComponent} from './hero-detail.component';

describe('HeroDetailComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [AppModule
      ],
      providers: [
        {provide: APP_BASE_HREF, useValue: '/'}
      ],
    }).compileComponents();
  }));

  it('should create hero detail component', (() => {
    const fixture = TestBed.createComponent(HeroDetailComponent);
    const component = fixture.debugElement.componentInstance;
    expect(component).toBeTruthy();
  }));
});

Błąd jest następujący:

Chrome 58.0.3029 (Mac OS X 10.12.6) HeroDetailComponent should create hero detail component FAILED
    Error: Illegal state: Could not load the summary for directive HeroDetailComponent.
        at syntaxError Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/~/@angular/compiler/@angular/compiler.es5.js:1690:22)
        at CompileMetadataResolver.getDirectiveSummary Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/~/@angular/compiler/@angular/compiler.es5.js:15272:1)
        at JitCompiler.getComponentFactory Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/~/@angular/compiler/@angular/compiler.es5.js:26733:26)
        at TestingCompilerImpl.getComponentFactory Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/~/@angular/compiler/@angular/compiler/testing.es5.js:484:1)
        at TestBed.createComponent Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/~/@angular/core/@angular/core/testing.es5.js:874:1)
        at Function.TestBed.createComponent Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/~/@angular/core/@angular/core/testing.es5.js:652:1)
        at UserContext.it Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/src/app/heroes/hero-detail/hero-detail.component.spec.ts:18:29)
        at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/~/zone.js/dist/zone.js:391:1)
        at ProxyZoneSpec.onInvoke Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/~/zone.js/dist/proxy.js:79:1)
        at ZoneDelegate.webpackJsonp.../../../../zone.js/dist/zone.js.ZoneDelegate.invoke Users/ismael.ramos.silvan/WebstormProjects/angular4-example-app/~/zone.js/dist/zone.js:390:1)

Możesz zobaczyć cały projekt, jeśli potrzebujesz więcej szczegółów.

UPDATE: dodano deklarację taką jak ta:

beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        AppModule
      ],
      declarations: [HeroDetailComponent],
      providers: [
        {provide: APP_BASE_HREF, useValue: '/'}
      ],
    }).compileComponents();
  }));

Teraz pojawiają się nowe błędy:

The pipe 'translate' could not be found ("<h1 class="section-title">{{[ERROR ->]'heroDetail' | translate}}</h1>
    <md-progress-spinner *ngIf="!hero"
                         class="progre"): ng:///DynamicTestModule/HeroDetailComponent.html@0:28
    Can't bind to 'color' since it isn't a known property of 'md-progress-spinner'.

I więcej ... to tak, jakby wszystkie dyrektywy i komponenty z materiału kątowego, a rura tłumaczona z ngx-translate / core nie wydaje się być uwzględniona ...

AKTUALIZACJA: OSTATECZNE ROZWIĄZANIE

Problem polegał na tym, że HeroesModule nie został nigdzie zaimportowany. To działa, ponieważ HeroesModule deklaruje HeroDetailComponent, co było początkowym problemem :

import {async, TestBed} from '@angular/core/testing';
import {APP_BASE_HREF} from '@angular/common';
import {AppModule} from '../../app.module';
import {HeroDetailComponent} from './hero-detail.component';
import {HeroesModule} from '../heroes.module';

describe('HeroDetailComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        AppModule,
        HeroesModule
      ],
      providers: [
        {provide: APP_BASE_HREF, useValue: '/'}
      ],
    }).compileComponents();
  }));

  it('should create hero detail component', (() => {
    const fixture = TestBed.createComponent(HeroDetailComponent);
    const component = fixture.debugElement.componentInstance;
    expect(component).toBeTruthy();
  }));
});
ismaestro
źródło
1
Nie musisz deklarować komponentu, aby go przetestować, wystarczy ustawić stanowisko testowe w nieco inny sposób: github.com/angular/angular/issues/17477#issuecomment-510397690
Stevanicus
Zamiast „AKTUALIZACJA: KOŃCOWE ROZWIĄZANIE”, prosimy o przesłanie własnej odpowiedzi , aby Twoje pytanie było wyraźnie oddzielone od rozwiązania, a rozwiązanie podlegało głosowaniu w górę / w dół wraz ze wszystkimi innymi możliwymi rozwiązaniami.
ggorlen

Odpowiedzi:

182

Przeszedłeś HeroDetailComponentdo TestBed.createComponent()bez uprzedniego deklarowania komponentu:

TestBed.configureTestingModule({
  imports: [AppModule,
     CommonModule,
     FormsModule,
     SharedModule,
     HeroRoutingModule,
     ReactiveFormsModule
  ],
  providers: [
    {provide: APP_BASE_HREF, useValue: '/'}
  ],
  declarations: [HeroDetailComponent]
}).compileComponents();

Mam nadzieję, że to pomoże.


Aktualizacja dotycząca następujących błędów w twoim teście: Dodano więcej importu (po prostu weź swój HeroModule jako plan, ponieważ w zasadzie to chcesz importować i udostępniać).

leksyt
źródło
Jeśli dodam tę deklarację, to pojawia się więcej błędów. Zaktualizowałem informacje, możesz to zobaczyć powyżej.
ismaestro
1
No ale w ten sposób pozbywasz się tego błędu. Następujące błędy mogą być kolejnym problemem z konfiguracją testu.
leksyta
Jaki błąd będzie następny?
leksyta
Nie można znaleźć potoku 'translate' ("<h1 class =" section-title "> {{[ERROR ->] 'heroDetail' | translate}} </h1> <md-progress-spinner * ngIf ="! hero "class =" progre "): ng: ///DynamicTestModule/HeroDetailComponent.html@0: 28 Nie można powiązać z„ kolorem ”, ponieważ nie jest to znana właściwość„ md-progress-spinner ”.
ismaestro
I nie zapominaj, że to się dzieje, ponieważ jest to leniwy moduł ładujący. Ponieważ inne testy, które mam, nie zawiodły ...
ismaestro
9

Brakuje deklaracji, musisz dodać testowaną klasę do deklaracji.

declarations: [component]
Akash Yellappa
źródło
W moim przypadku skopiowałem konfigurację TestBed z jednego komponentu do nowego, a następnie nie włączyłem testowanego komponentu.
Tonatio
3

Mój współpracownik i ja mieliśmy ten problem, ale poprawka była inna niż cokolwiek innego w Internecie.

Używamy Visual Studio Code i w nazwach folderów nie jest rozróżniana wielkość liter. Z tego powodu poprosiliśmy wszystkich o użycie konwencji nazewnictwa pisanych małymi literami, ale ostatecznie nazwa pisana wielkimi literami trafiła do kontroli źródła. Zmieniliśmy jego nazwę w okrężny sposób i wszystko było w porządku.

Miesiąc później mój współpracownik zaczął otrzymywać określony test jednostkowy, aby zerwać z tym komunikatem o błędzie. Podczas tego testu psował się tylko jego komputer. Dosłownie wykomentowaliśmy cały kod, który mógł wpływać na test, i nadal otrzymujemy błąd. Wreszcie przeszukałem globalnie klasę i zdaliśmy sobie sprawę, że nazwa folderu powróciła do nazwy pisanej wielkimi literami. Zmieniliśmy nazwę z powrotem na nazwę zapisaną małymi literami, bez rozpoznania żadnych oczekujących zmian, czy mogę dodać ... i test zadziałał.

Niech to będzie lekcja do podążania za wskazówkami dotyczącymi stylu. :)

Dla jasności poprawka była podobna do zmiany nazwy folderu FOOna foo.

christo8989
źródło
2

Ten typ błędu jest zgłaszany z powodu braku dodawania składnika w deklaracjach i usługach u dostawcy konfiguracji TestBed.

beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule.withRoutes([
        { path: 'home', component: DummyComponent },
        { path: 'patients/find', component: DummyComponent }
      ])],
      declarations: [RoutingComponent, DummyComponent,BreadcrumbComponent],
      providers : [BreadCrumbService]
    });
Vijay Barot
źródło
1

musisz zaimportować komponent HeroDetailComponent we właściwy sposób. Zauważ, że nawet wielkość liter ma znaczenie w ścieżkach. tzn. („@ angular / Forms” jest poprawne, ALE „@ angular / Forms” nie.

sami
źródło
1

Dla tych, którzy wciąż mają z tym problemy - przeczytałem osobny numer na githubie, w którym omówiono zmiany wprowadzone przez zespół Angulara w funkcji wywołania zwrotnego beforeEach.

Oto co zrobiłem:

beforeAll(async(() => {
    TestBed.configureTestingModule({
        declarations: [BannerNotificationComponent]
    }).compileComponents()

    fixture = TestBed.createComponent(BannerNotificationComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
}));

Użycie beforeAll rozwiązuje problem. Mam nadzieję, że pomoże to innym, ponieważ rozwiązanie tego niejasnego błędu zajęło mi około dnia.

Adam P.
źródło
0

Jeśli chcesz przetestować komponent bez kompilowania go, możesz zadeklarować go jako dostawcę:

beforeEach(() => {
  TestBed.configureTestingModule({
    // provide the component-under-test and dependent service
    providers: [
      WelcomeComponent,
      { provide: UserService, useClass: MockUserService }
    ]
  });
  // inject both the component and the dependent service.
  comp = TestBed.get(WelcomeComponent);
  userService = TestBed.get(UserService);
});

Zobacz: https://angular.io/guide/testing#component-test-basics

Stevanicus
źródło