web-dev-qa-db-fra.com

Erreur d'analyse du modèle dans le test Jasmine mais pas dans l'application réelle

J'ai développé une spécification Jasmine pour tester une composante MiddleRowComponent à 2 composantes angulaires. Lorsque je lance le test au jasmin, cela donne cette erreur:

zone.js:388 Unhandled Promise rejection: Template parse errors:
'circles' is not a known element:
1. If 'circles' is an Angular component, then verify that it is part of this module.
2. If 'circles' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("</div>
      <div class="col-md-10 col-sm-12 offset-md-1 flex-xs-middle" id="circles-div">
         [ERROR ->]<circles (onWordChanged)="onWordChanged($event)"></circles>
      </div>
      <div class="col-md-10 "): MiddleRowComponent@9:9
'custom-button' is not a known element:

Cependant, si je lance simplement mon application Web dans le navigateur comme d'habitude, l'erreur ne se produit pas. circles fait en effet partie du module. Et custom-button fait partie d'un module partagé importé. Voici le module.ts:

    import { NgModule }           from '@angular/core';
import { CommonModule }       from '@angular/common';
import { SharedModule } from '../shared/shared.module';
import * as LandingPage from './index';

@NgModule({
   imports: [ CommonModule, SharedModule ],
   declarations: [
      LandingPage.MiddleRowComponent,
      LandingPage.LandingPageComponent,
      LandingPage.CirclesComponent
   ],
   exports: [ LandingPage.LandingPageComponent ],
})
export class LandingPageModule { }

Tout est importé et déclaré comme il se doit et fonctionne lorsque vous exécutez l'application sans la tester. J'utilise une variable done pour effectuer le travail beforeEach étant donné sa nature asynchrone pour obtenir le modèle de composant à partir d'un fichier de modèle séparé. Je ruine le test avec un fichier HTML jasmine spec runner. Comment se fait-il que les composants que MiddleRowComponent utilise ne sont pas des éléments connus du test jasmine, mais le sont normalement lors de l'exécution de l'application?

Voici les spécifications de jasmin:

import 'zone.js/dist/long-stack-trace-zone.js';
import 'zone.js/dist/async-test.js';
import 'zone.js/dist/fake-async-test.js';
import 'zone.js/dist/sync-test.js';
import 'zone.js/dist/proxy.js';
import 'zone.js/dist/jasmine-patch.js';

import { ComponentFixture, TestBed } from '@angular/core/testing';
import {
    BrowserDynamicTestingModule,
    platformBrowserDynamicTesting
} from '@angular/platform-browser-dynamic/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

import { MiddleRowComponent } from './middle-row.component';

let comp: MiddleRowComponent;
let fixture: ComponentFixture<MiddleRowComponent>;
let de: DebugElement;
let el: HTMLElement;

describe('MiddleRowComponent', () => {
   var fixture: any;
   var comp: any;
    beforeAll(() => {
        TestBed.resetTestEnvironment();
        TestBed.initTestEnvironment(BrowserDynamicTestingModule,
            platformBrowserDynamicTesting());
    });

    beforeEach((done) => {
        TestBed.configureTestingModule({
            declarations: [MiddleRowComponent], // declare the test component
        }).compileComponents().then(() => {
            fixture = TestBed.createComponent(MiddleRowComponent);
            comp = fixture.componentInstance; // MiddleRowComponent test instance
            // query for the title <h1> by CSS element selector
            de = fixture.debugElement.query(By.css('h1'));
            el = de.nativeElement;
            done();
        });
    });

    it('should display original title', () => {
        fixture.detectChanges();
        expect(el.textContent).toContain(comp.Word);
    });

    it('should display a different test title', () => {
        comp.Word = 'Test Title';
        fixture.detectChanges();
        expect(el.textContent).toContain('Test Title');
    });
});

erreur complète:

zone.js:388 Unhandled Promise rejection: Template parse errors:
'circles' is not a known element:
1. If 'circles' is an Angular component, then verify that it is part of this module.
2. If 'circles' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("</div>
      <div class="col-md-10 col-sm-12 offset-md-1 flex-xs-middle" id="circles-div">
         [ERROR ->]<circles (onWordChanged)="onWordChanged($event)"></circles>
      </div>
      <div class="col-md-10 "): MiddleRowComponent@9:9
'custom-button' is not a known element:
1. If 'custom-button' is an Angular component, then verify that it is part of this module.
2. If 'custom-button' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
      </div>
      <div class="col-md-10 offset-md-1 flex-xs-middle" id="try-now-div">
         [ERROR ->]<custom-button buttonName="try now" (click)="tryNowClick()"></custom-button>
      </div>
   </div>
"): MiddleRowComponent@12:9 ; Zone: ProxyZone ; Task: Promise.then ; Value: Error: Template parse errors:(…) Error: Template parse errors:
'circles' is not a known element:
1. If 'circles' is an Angular component, then verify that it is part of this module.
2. If 'circles' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("</div>
      <div class="col-md-10 col-sm-12 offset-md-1 flex-xs-middle" id="circles-div">
         [ERROR ->]<circles (onWordChanged)="onWordChanged($event)"></circles>
      </div>
      <div class="col-md-10 "): MiddleRowComponent@9:9
'custom-button' is not a known element:
1. If 'custom-button' is an Angular component, then verify that it is part of this module.
2. If 'custom-button' is a Web Component then add "CUSTOM_ELEMENTS_SCHEMA" to the '@NgModule.schemas' of this component to suppress this message. ("
      </div>
      <div class="col-md-10 offset-md-1 flex-xs-middle" id="try-now-div">
         [ERROR ->]<custom-button buttonName="try now" (click)="tryNowClick()"></custom-button>
      </div>
   </div>
"): MiddleRowComponent@12:9
    at TemplateParser.parse (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:7730:21)
    at RuntimeCompiler._compileTemplate (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17573:53)
    at eval (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17493:64)
    at Set.forEach (native)
    at RuntimeCompiler._compileComponents (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17493:21)
    at createResult (http://localhost:3002/node_modules/@angular/compiler/bundles/compiler.umd.js:17404:21)
    at ZoneDelegate.invoke (http://localhost:3002/node_modules/zone.js/dist/zone.js:232:26)
    at ProxyZoneSpec.onInvoke (http://localhost:3002/node_modules/zone.js/dist/proxy.js:79:39)
    at ZoneDelegate.invoke (http://localhost:3002/node_modules/zone.js/dist/zone.js:231:32)
    at Zone.run (http://localhost:3002/node_modules/zone.js/dist/zone.js:114:43)consoleError @ zone.js:388_loop_1 @ zone.js:417drainMicroTaskQueue @ zone.js:421ZoneTask.invoke @ zone.js:339
zone.js:390 Error: Uncaught (in promise): Error: Template parse errors:(…)
16
BeniaminoBaggins

Eh bien, le module de votre test n’a déclaré que MiddleRowComponent. Donc, il ne sait pas à propos de CircleComponent:

TestBed.configureTestingModule({
    declarations: [MiddleRowComponent], // declare the test component
})

Ajoutez tous les composants nécessaires dans les déclarations du module de test ou ajoutez LandingPageModule aux importations du module de test.

21
JB Nizet

J'ai eu un problème similaire et j'ai trouvé cette page. La réponse de JB Nizet m'a permis de trouver une solution, mais elle n'a pas fonctionné en l'état. Je n'essaie pas de soustraire à sa solide réponse à la question initiale, mais simplement d'aider la prochaine personne qui vient.

Mon problème était exactement identique à celui du PO, sauf que mon composant personnalisé (MiddleRowComponent dans cet exemple) utilisait un composant tiers. L'erreur de test unitaire concernait la balise tierce utilisée dans mon modèle, même si cela fonctionnait parfaitement dans l'application réelle. La solution pour moi consistait également à inclure une imports pour le tiers dans mon module de test:

TestBed.configureTestingModule({
    declarations: [MiddleRowComponent],
    imports: [TheThirdPartyModule]
})

Ensuite, mes tests unitaires ont été exécutés sans l'erreur. J'espère que cela pourra aider!

4
Stokesified

Une autre option consiste à ajouter le schéma NO_ERRORS_SCHEMA à la configuration du test. Les composants non reconnus ne généreront plus d'erreur . Je l'utilise beaucoup lorsque je travaille avec des modules tiers tels que Angular Material Design.

import { NO_ERRORS_SCHEMA } from '@angular/core';
...
  beforeEach(
    async(() => {
      TestBed.configureTestingModule({
        declarations: [MiddleRowComponent],
        schemas: [NO_ERRORS_SCHEMA]
      }).compileComponents();
    })
  );
1
Kildareflare