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.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).
api-connector-service.spec.ts
(fichier de spécifications de ApiConnectorService
) à partir de mes tests chargés, les tests de ApiService
réussiront.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.
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');
});
})));
});
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.
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
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.