简体   繁体   中英

Play 2.5 Guice errors when compiling

I am currently in the process of migrating my app from Play 2.4 to Play 2.5 So far, it's been a massive pain.

Right now, I am trying to make my tests to pass.

I have one controller with some injected params

class UserLogin @Inject() (
    loginService: UserLoginService,
    authConfig: AuthConfig,
    oAuthConfig: OAuthConfig,
    env: PureEnvironment,
    //stringResources: StringResources,
    messagesApi: MessagesApi
  ) extends BaseController(messagesApi: MessagesApi) {

  //endpoints
}

From the testing side, I have them defined to be injected with Guice

object IdentityManagerModuleMock extends AbstractModule with ScalaModule {
  def configure: Unit = {
    bind[PureEnvironment].toInstance(MockEnvironment)
    val conf = Configuration.reference
    val messagesApi = new DefaultMessagesApi(Environment.simple(), conf, new DefaultLangs(conf))
    bind[MessagesApi].toInstance(messagesApi)

    bind[AuthConfig].toInstance(
      AuthConfig(
        "https://localhost",
        30,
        3600,
        86400,
        Seq(InetAddress.getByName("127.0.0.1")),
        Seq(InetAddress.getByName("127.0.0.1")),
        "https://localhost/login"
      )
    )
    bind[OAuthConfig].toInstance(oAuthConfigMock)

    bind[UserLoginService].to[UserLoginServiceImpl]
}

val injector = Guice.createInjector(IdentityManagerModuleMock)

When I enable the routes in my routes file, 
POST    /login com.dummy.im.controllers.UserLogin.login
POST    /reset com.dummy.im.controllers.UserLogin.reset

1) No implementation for com.dummy.im.components.UserLoginService was bound.
[info]   while locating com.dummy.im.components.UserLoginService
[info]     for parameter 0 at com.dummy.im.controllers.UserLogin.<init>(UserLogin.scala:24)
2) No implementation for com.dummy.platform.PureEnvironment was bound.
[info]   while locating com.dummy.platform.PureEnvironment
[info]     for parameter 3 at com.dummy.im.controllers.UserLogin.<init>(UserLogin.scala:24)
3) No implementation for scala.collection.Seq<java.net.InetAddress> was bound.
[info]   while locating scala.collection.Seq<java.net.InetAddress>
[info]     for parameter 4 at com.dummy.im.config.AuthConfig.<init>(AuthConfig.scala:13)

5) Could not find a suitable constructor in java.lang.Integer. Classes must have either one 
(and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
[info]   at java.lang.Integer.class(Integer.java:52)
[info]   while locating java.lang.Integer
[info]     for parameter 1 at com.dummy.im.config.AuthConfig.<init>(AuthConfig.scala:13)

The weird thing is that I have a very similar config for actual running the app, without the MessagesAPI (injected by Play, as far as I know) and those config objects which are read from the .conf file.

object IdentityManagerModule extends AbstractModule with ScalaModule {

  def configure: Unit = {
    bind[PureEnvironment].to[PlayProductionEnvironmentImpl]

    bind[OauthRepository].to[OauthRepositoryImpl]

    bind[UserLoginService].to[UserLoginServiceImpl]
  }
}

And it runs just fine.

The main thing that I changed was to add the dependency to MessagesAPI in the controller.

I don't understand why Guice fails to see the things that are binded in IdentityManagerModuleMock.

Any ideas are more than welcomed. I have read and tried all I could think of for the past several days.

EDIT: We have a custom app loader

class CustomApplicationLoader extends GuiceApplicationLoader() {
  //config validation

  override def builder(context: ApplicationLoader.Context): GuiceApplicationBuilder = {
    val conf = context.initialConfiguration
    initialBuilder
      .in(context.environment)
      .loadConfig(conf)
      .overrides(overrides(context): _*)
      .bindings(
        MiscModule,
        CommonConfigurationModule,
        IdentityManagerConfigModule,
        IdentityManagerModule,
        ApplicationLifecycleModule
      )
  }
}

In the .conf file, it's used as

play.application.loader = "com.dummy.guice.CustomApplicationLoader"

It doesn't look like you need a custom application loader for what you're doing. If you disable the out of the box MessagesApi and then add your own modules through application.conf , that should mean you don't have to override MessagesApi.

https://www.playframework.com/documentation/2.5.x/ScalaPlayModules#Registration-Overrides

If you're running tests involving Guice, you can use WithApplication .

https://www.playframework.com/documentation/2.5.x/ScalaFunctionalTestingWithSpecs2#WithApplication

You shouldn't ever have to call Guice.createInjector directly, because WithApplication will call out to GuiceApplicationBuilder:

https://www.playframework.com/documentation/2.5.x/ScalaTestingWithGuice#GuiceApplicationBuilder

Check out the example projects: they all have "2.5.x" branches and most have tests integrated into them, and leverage them as a guide:

https://github.com/playframework?utf8=%E2%9C%93&q=examples&type=&language=

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM