Angular Ошибка Karma Jasmine: Незаконное состояние: не удалось загрузить сводку для директивы

Я разрабатываю github-репозиторий (с angular 7 и angular-cli), и у меня есть несколько тестов с Кармой и Жасмин, работающими в основной ветке.

Сейчас я пытаюсь добавить функцию отложенной загрузки, дело в том, что тесты, которые раньше проходили, сейчас их нет. Забавно, потому что проваливаются только тесты из ленивого загрузочного модуля...

Вот код и ошибка:

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

Ошибка заключается в следующем:

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)

Вы можете увидеть весь проект, для более подробной информации, если вам это нужно.

ОБНОВЛЕНИЕ: добавлено объявление, как это:

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

Теперь появляются новые ошибки:

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

И еще... это, как и все директивы и компоненты из углового материала, и труба translate из ngx-translate/core, похоже, не включена...

ОБНОВЛЕНО: ЗАКЛЮЧИТЕЛЬНОЕ РЕШЕНИЕ

Проблема была в том, что HeroesModule нигде не был импортирован. Это работает, потому что HeroesModule объявляет HeroDetailComponent, который был первоначальной проблемой:

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

Ответ 1

Вы передали HeroDetailComponent в TestBed.createComponent() без предварительного объявления компонента:

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

Надеюсь, что это поможет.


Обновление для следующих ошибок в вашем тесте: добавлено несколько импортных ресурсов (просто возьмите свой HeroModule в качестве плана, потому что в основном вы хотите импортировать и предоставить).

Ответ 2

Вы пропускаете объявления, вам нужно добавить тестируемый класс в объявления.

declarations: [component]

Ответ 3

Этот тип ошибки возникает из-за отсутствия добавления компонента в объявлениях и службах в поставщике конфигурации TestBed.

beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [RouterTestingModule.withRoutes([
        { path: 'home', component: DummyComponent },
        { path: 'patients/find', component: DummyComponent }
      ])],
      declarations: [RoutingComponent, DummyComponent,BreadcrumbComponent],
      providers : [BreadCrumbService]
    });

Ответ 4

У меня и моего коллеги была эта проблема, но ее решение отличалось от всего остального в Интернете.

Мы используем код Visual Studio и имена папок не чувствительны к регистру. Из-за этого мы попросили всех использовать соглашение об именах в нижнем регистре, но в конечном итоге имя верхнего регистра попало в систему контроля версий. Мы переименовали его окольным путем, и все было хорошо.

Месяц спустя мой коллега начал получать специальный unit тест с этим сообщением об ошибке. Только его компьютер ломался в этом тесте. Мы буквально закомментировали весь код, который мог повлиять на тест, и все равно получили ошибку. Наконец, я глобально искал класс, и мы поняли, что имя папки вернулось к имени в верхнем регистре. Мы переименовали его обратно в строчное имя без ожидающих изменений, я мог бы добавить..., и тест сработал.

Пусть это будет уроком для руководства по стилю. :)

Для ясности, исправление было похоже на изменение имени папки FOO на foo.

Ответ 5

вы должны импортировать компонент HeroDetailComponent правильным способом. Обратите внимание на, что даже случай букв - это вопрос по путям. i.e('@angular/forms' является правильным, НО '@ angular/Формы' не является.

Ответ 6

Если вы хотите протестировать компонент без его компиляции, вы можете объявить его провайдером:

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

Смотрите: https://angular.io/guide/testing#component-test-basics

Ответ 7

Для тех, у кого все еще есть проблемы с этим - я прочитал отдельную проблему github, в которой обсуждались изменения, внесенные командой Angular в функцию обратного вызова beforeEach.

Вот что я сделал:

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

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

Использование beforeAll устраняет проблему. Надеюсь, что это поможет другим, так как мне понадобилось около дня, чтобы решить эту неясную ошибку.