web-dev-qa-db-fra.com

Test - Impossible de résoudre tous les paramètres de (ClassName)

Le contexte

J'ai créé une classe ApiService pour pouvoir gérer nos requêtes API personnalisées, tout en utilisant notre propre sérialiseur et d'autres fonctionnalités.

La signature du constructeur de ApiService est:

constructor(metaManager: MetaManager, connector: ApiConnectorService, eventDispatcher: EventDispatcher);
  • MetaManager est un service injectable qui gère les métadonnées d'API.
  • ApiConnectorService est un service qui enveloppe Http pour ajouter nos en-têtes personnalisés et notre système de signature.
  • EventDispatcher est fondamentalement le système de répartiteur d'événements de Symfony, en TypeScript.

Problème

Lorsque je teste le ApiService, je fais une initialisation dans beforeEach:

beforeEach(async(() => {
    TestBed.configureTestingModule({
        imports  : [
            HttpModule
        ],
        providers: [
            ApiConnectorService,
            ApiService,
            MetaManager,
            EventDispatcher,
            OFF_LOGGER_PROVIDERS
        ]
    });
}));

et ça marche bien.

Ensuite, j'ajoute mon deuxième fichier de spécifications, qui est pour ApiConnectorService, avec ce beforeEach:

beforeEach(async(() => {
    TestBed.configureTestingModule({
        imports  : [HttpModule],
        providers: [
            ApiConnectorService,
            OFF_LOGGER_PROVIDERS,
            AuthenticationManager,
            EventDispatcher
        ]
    });
}));

Et tous les tests échouent avec cette erreur:

Erreur: impossible de résoudre tous les paramètres d'ApiService: (MetaManager,?, EventDispatcher).

  • Si je supprime api-connector-service.spec.ts (fichier de spécifications de ApiConnectorService) à partir de mes tests chargés, les tests de ApiService réussiront.
  • Si je supprime api-service.spec.ts (fichier de spécifications de ApiService) à partir de mes tests chargés, les tests de ApiConnectorService réussiront.

Pourquoi ai-je cette erreur? Il semble que le contexte entre mes deux fichiers soit en conflit et je ne sais pas pourquoi et comment y remédier.

16
Supamiu

C'est parce que le service Http ne peut pas être résolu à partir de HttpModule, dans un environnement de test. Cela dépend du navigateur de la plateforme. Vous ne devriez même pas essayer de faire des appels XHR de toute façon pendant les tests.

Pour cette raison, Angular fournit un MockBackend pour le service Http à utiliser. Nous utilisons ce faux moteur pour souscrire aux connexions dans nos tests, et nous pouvons se moquer de la réponse lorsque chaque connexion est établie.

Voici un court exemple complet sur lequel vous pouvez travailler

import { Injectable } from '@angular/core';
import { async, inject, TestBed } from '@angular/core/testing';
import { MockBackend, MockConnection } from '@angular/http/testing';
import {
  Http, HttpModule, XHRBackend, ResponseOptions,
  Response, BaseRequestOptions
} from '@angular/http';

@Injectable()
class SomeService {
  constructor(private _http: Http) {}

  getSomething(url) {
        return this._http.get(url).map(res => res.text());
  }
}

describe('service: SomeService', () => {
  beforeEach(() => {
        TestBed.configureTestingModule({
          providers: [
                {
                  provide: Http, useFactory: (backend, options) => {
                        return new Http(backend, options);
                  },
                  deps: [MockBackend, BaseRequestOptions]
                },
                MockBackend,
                BaseRequestOptions,
                SomeService
          ]
        });
  });

  it('should get value',
        async(inject([SomeService, MockBackend],
                                 (service: SomeService, backend: MockBackend) => {

        backend.connections.subscribe((conn: MockConnection) => {
          const options: ResponseOptions = new ResponseOptions({body: 'hello'});
          conn.mockRespond(new Response(options));
        });

        service.getSomething('http://dummy.com').subscribe(res => {
          console.log('subcription called');
          expect(res).toEqual('hello');
        });
  })));
});
16
Paul Samsotha

Le problème n'a pas été vraiment résolu dans la réponse choisie, qui est vraiment juste une recommandation pour écrire des tests, mais plutôt dans les commentaires, et vous devez suivre un lien et le rechercher là-bas. Étant donné que j'ai eu un autre problème avec la même erreur, je vais ajouter les deux solutions ici.

  1. Solution au problème du PO:

Si vous avez un baril (index.ts ou fichier multi export) comme celui-ci:

export * from 'my.component' // using my.service via DI
export * from 'my.service'

Ensuite, vous pourriez obtenir une erreur comme EXCEPTION: Can't resolve all parameters for MyComponent: (?).

Pour y remédier, vous devez exporter le service avant le composant:

export * from 'my.service'
export * from 'my.component' // using my.service via DI
  1. Solution à mon problème:

La même erreur peut se produire en raison d'un circular dependency Qui provoque une importation de service undefined. Pour vérifier, console.log(YourService) après l'avoir importé (dans votre fichier de test - où le problème se produit). S'il n'est pas défini, vous pouvez avoir créé un fichier index.ts (baril) exportant à la fois le service et le fichier en l'utilisant (composant/effet/tout ce que vous testez) - en important le service à partir du fichier d'index où les deux sont exportés ( ce qui en fait un cercle complet).

Recherchez ce fichier et importez le service dont vous avez besoin directement à partir du fichier your.service.ts Au lieu de l'index.

7
Kesarion