web-dev-qa-db-fra.com

Test unitaire du composant angular2 avec module importé

J'essaie d'écrire un test sur un composant qui utilise angular-material2, mais quand je l'ajoute à mes déclarations testModule, j'obtiens:

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

L'ajout de MaterialModule aux déclarations génère `Erreur: module inattendu 'MaterialModule' déclaré par le module

DynamicTestModule 'dans config/spec-bundle.js (ligne 24994)

Voici à quoi ressemble mon fichier de spécifications:

  beforeEach(() => TestBed.configureTestingModule({
    declarations: [],
    providers: [
      { provide: DataService, useValue: mockDataService },
      { provide: ActivatedRoute, useClass: MockActivatedRoute },
      { provide: Router, useValue: mockRouter },
      CellViewComponent
    ]
  }));

l'ajout de CellViewComponent au tableau de déclarations provoque le déclenchement de l'erreur.

10
George Edwards

Lorsque vous utilisez le TestBed.configureTestingModule, vous créez un module à partir de zéro pour l'environnement de test. Donc, quoi que vous ayez besoin dans la vraie application pour que le CellViewComponent fonctionne, vous devez également le configurer dans le module de test.

Dans votre cas, il vous manque le composant de la carte Matériel. Dans l'application, vous avez probablement importé le MaterialModule ou le MdCardModule dans votre AppModule. Vous devez donc faire de même dans le module de test

beforeEach(() => TestBed.configureTestingModule({
  imports: [ MaterialModule /* or MdCardModule */ ],
  declarations: [  CellViewComponent ],
  providers: [
    { provide: DataService, useValue: mockDataService },
    { provide: ActivatedRoute, useClass: MockActivatedRoute },
    { provide: Router, useValue: mockRouter },
  ]
}));
19
Paul Samsotha

C'est un vrai problème: vous pouvez tout simuler sauf le sélecteur du composant importé.

Il existe un moyen simple. Cela permet d'éviter d'importer les modules, vous pouvez simplement désactiver ce type d'erreurs.

Ajoutez simplement ceci à votre module:

import { NO_ERRORS_SCHEMA } from '@angular/core';

...

TestBed.configureTestingModule({
  schemas: [ NO_ERRORS_SCHEMA ],
  ...

Lien vers les documents Angular2

Oui, cela n'aidera pas si vous voulez faire des tests d'intégration (non isolés), mais cela fonctionne parfaitement pour les tests isolés.

Même si vous décidiez d'importer un module, je pense qu'il serait plus correct d'importer le module factice avec tous les sélecteurs implémentés à la place.

6
smnbbrv

Ce que je fais souvent, lors du test de nos composants d'application Angular, c'est juste d'importer le module parent via une référence. Pour la plupart des cas d'utilisation, c'est suffisant ou presque suffisant et si vous changez le composant, via en ajoutant de nouvelles déclarations ou importations, vous n'avez pas à vous soucier de modifier le fichier de test, car le fichier de test importe le module parent.

Je ne change que le module pour importer des composants externes à des fins de test, mais c'est rare.

Pseudo-code d'initialisation de test régulier

beforeEach(() => TestBed.configureTestingModule({
    declarations: [
        ComponentA,
        ComponentB
    ],
    providers: [
        CellViewComponent
    ]
}));

disons que ce composant est dans un module. J'ai mis l'objet de déclarations dans une variable à utiliser simultanément dans ParentModule et Testing.

export var ParentModuleArgs = {
    declarations: [
        ComponentA,
        ComponentB
    ],
    providers: [
        CellViewComponent
    ]
  };

@NgModule(parentModuleArgs)
export class ParentModule {}

Ensuite, au lieu de réécrire tout le tableau de modules dans le composant de test et d'être très non DRY, je le fais.

beforeEach(() => TestBed.configureTestingModule(ParentModuleArgs));

Et si j'ai besoin d'ajouter quelque chose, nous pouvons simplement l'ajouter avant de configurer le banc d'essai

let moduleArgs: NgModule = ParentModuleArgs;
moduleArgs.providers.Push({provide: APP_BASE_HREF, useValue: '/'});

beforeEach(() => TestBed.configureTestingModule(ParentModuleArgs));
0
Karl Johan Vallner