2017-05-30 7 views
1

私は依存関係としてサービスを持つコンポーネントのユニットテストについて質問しており、このサーバーはHttpに依存しています。 私は、このドキュメントを読んでいます:Test a component with an async serviceHttpサービスに依存する別のサービスに依存するサービス/コンポーネントをテストするには?

私は、この例のように実際には同じコードがあります。ここにところで

ngOnInit(): void { 
    this.twainService.getQuote().then(quote => this.quote = quote); 
    } 

が私のコードです:code

ドキュメントは、私はコンポーネントをテストするときと言います他のサービスに依存している場合、私は:

  1. このサービスをモジュールプロバイダーとして設定してください
  2. コンポーネントに注入
  3. GETサービス:その上twainService = fixture.debugElement.injector.get(TwainService);

  4. セットアップスパイ:spy = spyOn(twainService, 'getQuote').and.returnValue(Promise.resolve(testQuote));

は、私は、同じ操作を行います。spec file: はここに私のspecファイルです。 は、私はそうは32

質問に29とIセットアップのスパイにサービスを注入します、ライン21でサービスを提供します。Error: No provider for Http!:私はドキュメントのようにすべてを行う場合、私はエラーを取得していますと言います。私のGoodsDataServiceHttpサービスに依存しているので、明らかにこのエラーが表示されます。私はそれをどのように扱うべきですか?私はこれをやった:私は単純なjavascriptオブジェクトを作成し、私は実際にGoodsDataServiceを嘲笑した。また、このオブジェクトにメソッドスタブgetGoodsを追加しました。これらのすべての事柄は、実際に注入することなくメインコンポーネントをテストすることを可能にしますGoodsDataService。しかし、私はこの解決策について全くわかりません。私はそれが汚れていて正しいとは思わない。 Httpサービスに依存する別のサービスに依存するユニットテストコンポーネント/サービスの正しい方法は何ですか?何かご意見は?

答えて

1

テストモジュールのインポートにHttpModuleを追加するだけです。

あなたのservieにHttpを注入できるようにする必要がありますが、Httpはあなたのサービスメソッドを偵察しているので、あなたのテストでは使用されません。

+0

これは本当に良いアイデアだと思います。私は同じことを考えていた。しかし、どうしてdocsはそれを言っていないのですか?それは何か明白ですか? –

+0

わかりやすいとは言いません。すべてのことを理解するには時間がかかります。しかし、私はそれがどのように起こったのかを理解すれば、それは論理的に聞こえると言うでしょう。私は、HTTPを使ったサービスとしてtwainサービスを導入したことを考えると、テストで偽のHttpサービスを提供する方法や、HttpModuleをインポートする方法を説明する必要があることに同意します。問題を開く必要があります。 –

0

要約:はい、依存関係スタブと非同期サービスの組み合わせを使用してください。

TwainServiceは、実際にはまったくHttpまたは他の依存関係を使用していない、それだけの約束を返すことが判明:私たちの例では、テスト中の構成要素が潜在的に持っているサービスに依存しているのでそう

getQuote(): Promise<string> { 
    return new Promise(resolve => { 
     setTimeout(() => resolve(this.nextQuote()), 500); 
    }); 
} 

をそれ自身の依存関係がたくさんあるので、AngularドキュメントのWelcomeComponent/userServiceStubの例を使ってそのサービスを模擬するのが最も良い方法です。スタブオブジェクトは実際のメソッド名のプロパティを持ち、その値はそのステートメントを持つ名前のない関数です。

実際のメソッドが非同期に返っても、同期的に返すメソッドをスタブに誤って実装するのは簡単です。実際の非同期メソッドの応答を処理するブロックが.then()のブロックに含まれている可能性があるため、これを行う必要はありません。したがって、あなたのスタブメソッドが約束で包まれたテスト戻り値を返すことを確認してください:return Promise.resolve(mySwappableTestingReturnValue)。角度のasync()/whenStable.then()、角度のfakeAsync()/tick()、またはジャスミンのdone:私たちは実際に非同期メソッド(警告)をテストしているので、

最後に、itブロックもTwainService例では3つのオプションのいずれかを使用する必要があります。私はまた、約束の普通の.then()ブロックがfixture.componentInstance.myAsyncMethod()に付加されていることが同様にうまくいくことを発見しました(また、jsのasync/awaitもそうです)。スパイルーキーとして

~~~

、私はまた.and.callThrough()はあなたを助けるかもしれないもう一つのミスを犯しました。

たとえば、(ユーモアme、それは短いと一般的です):LoginComponentはsubmit.batを持っていますonclickはthis.authService.askAuthServerを呼び出すlogMeInメソッドによって処理されます。 askAuthServerはHTTPを使用します。

ボタンクリックが正しくlogMeInを呼び出すかどうかをテストする仕様は同期的ですが、logMeInから返された値は気にせず、呼び出されたことだけを気にします(UIイベントは、それがあなたを助けるなら)。 logMeIn内の判定ロジックをテストする仕様は戻り値を必要とするため、非同期的にテストする必要がありますので、whenStable().then()を使用してください。

したがって、beforeEachにspyOn logMeInを作成しても、クリックのスペックは成功し、非同期ロジック仕様は失敗します。クリックスペックでは、スパイは正常に.toHaveBeenCalled()になりますが、askAuthServerは実行されません。何が起こっている? logMeInの復帰を待つことを選択しないうちに、スパイがlogMeInの実行を妨げたからです。ロジック仕様では、logMeInSpyを使用しないかもしれませんが、非同期パーツを正しく設定したとしても、スパイはまだlogMeIn(とaskAuthServer)の実行を妨げています。 beforeEachでスパイを作成するときにに、.and.callThrough()を使用するか、ということを理解

は、両方のスペック中のLogMeInの実行を許可するか、それがロジックの仕様には影響しませんクリック仕様にスパイを移動します。

関連する問題