2016-11-30 9 views
0

Play Frameworkによって提供されるWsTestClientを使用してWebサービスを模擬しようとしています。 Play FrameworkのWSTestClientを使用した機能テストによるcom.google.inject.CreationException

import javax.inject.Inject 

import org.scalatest.FunSuite 
import play.api.inject.guice.GuiceApplicationBuilder 
import play.core.server.Server 
import play.api.routing.sird._ 
import play.api.mvc._ 
import play.api.libs.json._ 
import play.api.test._ 
import play.api.inject._ 
import play.api.libs.ws.WSClient 
import scala.concurrent.Await 

class Service @Inject()(wsClient:WSClient) { 
    def query = wsClient.url("/service").get() 
} 

class WebServiceMockingRequestSuite extends FunSuite { 

    test("Webservice request") { 

    Server.withRouter() { 
     case GET(p"/service") => Action { 
      Results.Ok(JsNumber(42)) 
     } 
     } { implicit port => 
     WsTestClient.withClient { client => 

      val app = GuiceApplicationBuilder().bindings(bind[WSClient].to(client)) 
      val service = app.injector.instanceOf[Service] 

      import concurrent.duration._ 
      val response = Await.result(service.query,3.seconds) 
      assert(response.body == "42") 
     } 
     } 
    } 
} 

しかし、テストアプリケーションの起動時に、私は次の例外に走った:プレイ・テスト・アプリケーションに WsTestClientインスタンスを注入

はまっすぐ前方に見えたそれを注意することは興味深いことである

[info] - Mocked webservice request *** FAILED *** 
[info] com.google.inject.CreationException: Unable to create injector, see the following errors: 
[info] 
[info] 1) A binding to play.api.libs.ws.WSClient was already configured at playsample.webservice.tests.WebServiceMockingRequestSuite$$anonfun$1$$anonfun$apply$mcV$sp$2$$anonfun$apply$1.apply(WebServiceMockingTestSuite.scala:32): 
[info] Binding(interface play.api.libs.ws.WSClient to ProviderTarget([email protected])) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1). 
[info] at play.api.libs.ws.ahc.AhcWSModule.bindings(AhcWS.scala:374): 
[info] Binding(interface play.api.libs.ws.WSClient to ProviderConstructionTarget(class play.api.libs.ws.ahc.WSClientProvider) in interface javax.inject.Singleton) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1) 
[info] 
[info] 1 error 
[info] at com.google.inject.internal.Errors.throwCreationExceptionIfErrorsExist(Errors.java:466) 
[info] at com.google.inject.internal.InternalInjectorCreator.initializeStatically(InternalInjectorCreator.java:155) 
[info] at com.google.inject.internal.InternalInjectorCreator.build(InternalInjectorCreator.java:107) 
[info] at com.google.inject.Guice.createInjector(Guice.java:96) 
[info] at com.google.inject.Guice.createInjector(Guice.java:84) 
[info] at play.api.inject.guice.GuiceBuilder.injector(GuiceInjectorBuilder.scala:181) 
[info] at playsample.webservice.tests.WebServiceMockingRequestSuite$$anonfun$1$$anonfun$apply$mcV$sp$2$$anonfun$apply$1.apply(WebServiceMockingTestSuite.scala:33) 
[info] at playsample.webservice.tests.WebServiceMockingRequestSuite$$anonfun$1$$anonfun$apply$mcV$sp$2$$anonfun$apply$1.apply(WebServiceMockingTestSuite.scala:30) 
[info] at play.api.test.WsTestClient$class.withClient(WSTestClient.scala:79) 
[info] at play.api.test.WsTestClient$.withClient(WSTestClient.scala:87) 

インスタンスが次のように直接注入されていれば、問題なく動作します。

test("Webservice request without service instance") { 

    Server.withRouter() { 
     case GET(p"/service") => Action { 
     Results.Ok(JsNumber(42)) 
     } 
    } { implicit port => 

     WsTestClient.withClient { client => 

     val app = GuiceApplicationBuilder().bindings(bind[WSClient].to(client)) 

     import concurrent.duration._ 
     val response = Await.result(client.url("/service").get(),3.seconds) 
     assert(response.body == "42") 
     } 
    } 
} 

このテストは、com.google.inject.CreationExceptionの例外をスローすることなく、期待どおりに実行されます。

+0

をあなたが必要とするすべては 'client'、なぜ全体のアプリケーションを作成するということですか? – rethab

+0

アプリケーション全体( 'GuiceApplicationBuilder'でスピンアップ)は、' Server.withRouter() 'によってランダムなポートで開始されたWebサービスとやりとりすることができます。 私は[play-mockws](https://github.com/leanovate/play-mockws)を見つけました。これは、外部のWebサービスの応答を模倣するのに効果的です。 –

答えて

0

Play FrameworkのドキュメントのTesting with Guiceページで詳細を読んだところ、問題を解決できました。

A binding to play.api.libs.ws.WSClient was already configured)上記投げ式で与えられたヒントに続いて、私は期待通りのテスト作業をするために

val app = GuiceApplicationBuilder().overrides(bind[WSClient].to(client)) 

val app = GuiceApplicationBuilder().bindings(bind[WSClient].to(client)) 

を置き換えます。

次のテストはうまく今取り組んでいる:

import javax.inject.Inject 

import org.scalatest.FunSuite 
import play.api.inject.guice.GuiceApplicationBuilder 
import play.core.server.Server 
import play.api.routing.sird._ 
import play.api.mvc._ 
import play.api.libs.json._ 
import play.api.test._ 
import play.api.inject._ 
import play.api.libs.ws.WSClient 
import scala.concurrent.Await 

class Service @Inject()(wsClient:WSClient) { 
    def query = wsClient.url("/service").get() 
} 

class WebServiceMockingRequestSuite extends FunSuite { 

    test("Webservice request") { 

    Server.withRouter() { 
     case GET(p"/service") => Action { 
      Results.Ok(JsNumber(42)) 
     } 
     } { implicit port => 
     WsTestClient.withClient { client => 

      val app = GuiceApplicationBuilder().overrides(bind[WSClient].to(client)) 
      val service = app.injector.instanceOf[Service] 

      import concurrent.duration._ 
      val response = Await.result(service.query,3.seconds) 
      assert(response.body == "42") 
     } 
     } 
    } 
} 
関連する問題