web-dev-qa-db-ja.com

テスト-(ClassName)のすべてのパラメーターを解決できない

環境

独自のシリアライザーとその他の機能を使用しながら、カスタムAPIクエリを処理できるようにApiServiceクラスを作成しました。

ApiServiceのコンストラクタシグネチャは次のとおりです。

constructor(metaManager: MetaManager, connector: ApiConnectorService, eventDispatcher: EventDispatcher);
  • MetaManagerは、APIのメタデータを処理する注入可能なサービスです。
  • ApiConnectorServiceは、カスタムヘッダーと署名システムを追加するためにHttpをラップするサービスです。
  • EventDispatcherは、基本的にはTypeScriptのSymfonyのイベントディスパッチャーシステムです。

問題

ApiServiceをテストするとき、beforeEachで初期化を行います。

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

そしてそれは正常に動作します。

次に、ApiConnectorService用の2番目のspecファイルを、次のbeforeEachとともに追加します。

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

そして、すべてのテストはこのエラーで失敗します:

エラー:ApiServiceのすべてのパラメーターを解決できません:(MetaManager、?、EventDispatcher)。

  • ロードしたテストからapi-connector-service.spec.tsApiConnectorServiceのspecファイル)を削除すると、ApiServiceのテストは成功します。
  • ロードしたテストからapi-service.spec.tsApiServiceのspecファイル)を削除すると、ApiConnectorServiceのテストは成功します。

なぜこのエラーが発生するのですか? 2つのファイル間のコンテキストが競合しているようで、これを修正する理由と方法がわかりません。

16
Supamiu

テスト環境では、HttpサービスをHttpModuleから解決できないためです。プラットフォームブラウザに依存します。とにかく、テスト中にXHRを呼び出そうとしてもいけません。

このため、AngularはMockBackendサービスに使用するHttpを提供します。このモックバックエンドを使用して、テストで接続をサブスクライブします。各接続が行われたときに応答をモックします。

ここにあなたが仕事をすることができる短い完全な例があります

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

この問題は、選択した回答で実際に解決されたわけではなく、テストを書くための推奨事項にすぎず、むしろコメントにあります。リンクをたどってそこを検索する必要があります。同じエラーで別の問題が発生したため、ここで両方のソリューションを追加します。

  1. OPの問題の解決策:

次のようなバレル(index.tsまたはマルチエクスポートファイル)がある場合:

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

その後、EXCEPTION: Can't resolve all parameters for MyComponent: (?)のようなエラーが発生する可能性があります。

修正するには、コンポーネントの前にサービスをエクスポートする必要があります。

_export * from 'my.service'
export * from 'my.component' // using my.service via DI
_
  1. 私の問題の解決策:

undefinedサービスのインポートを引き起こす_circular dependency_により、同じエラーが発生する可能性があります。確認するには、console.log(YourService)をインポートした後(テストファイルで-問題が発生している場所)。定義されていない場合は、index.tsファイル(バレル)を作成して、サービスとそれを使用するファイル(コンポーネント/効果/テストするもの)の両方をエクスポートしている可能性があります-両方がエクスポートされているインデックスファイルからサービスをインポートする(完全な円にする)。

そのファイルを見つけ、必要なサービスをインデックスではなく_your.service.ts_ファイルから直接インポートします。

7
Kesarion