使用Play Framework的WSTestClient进行功能测试的com.google.inject.CreationException

时间:2016-11-30 17:17:50

标签: scala playframework guice

我试图使用Play Framework提供的WsTestClient来模拟网络服务。

将一个WsTestClient实例注入Play测试应用程序似乎很简单:

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")
        }
      }
  }
}

但是在测试应用程序启动期间,我遇到了以下异常:

[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(play.api.inject.BindingKey$$anon$1@5488669d)) (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)

有趣的是,如果直接注入WSTestClient实例,事情就可以了。

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异常。

1 个答案:

答案 0 :(得分:0)

在Play Framework文档的Testing with Guice页面上阅读了更多内容后,我能够解决问题。

按照上面抛出的表达式(A binding to play.api.libs.ws.WSClient was already configured)中给出的提示,我替换了

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

val app = GuiceApplicationBuilder().overrides(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")
        }
      }
  }
}