Thanks for your reply, Greg. But I have some further questions.
We are using Guice to create the app for both production and tests.
This is how I
class MyApplicationBuilder(dbSuffix: LiveDBID = nextDbId) {
def build(): Application = {
val env = Environment.simple()
val context = ApplicationLoader.Context(
environment = env,
sourceMapper = None,
webCommands = new DefaultWebCommands(),
initialConfiguration = Configuration.load(env),
lifecycle = new DefaultApplicationLifecycle()
)
val myEnv = new MockEnvironment
val app = new MyApplicationLoader()
.builder(context)
.overrides(new OverridingEnvironmentModule(myEnv))
.bindings(bind[LiveDBID].toInstance(dbSuffix))
.build()
val lifeCycle = app.injector.instanceOf[play.api.inject.ApplicationLifecycle]
new ApplicationStopper(lifeCycle, myEnv, dbSuffix)
app
}
}
class MyApplicationLoader extends GuiceApplicationLoader {
override def builder(context: ApplicationLoader.Context): GuiceApplicationBuilder = {
val conf = context.initialConfiguration
initialBuilder
.in(context.environment)
.loadConfig(conf)
.overrides(overrides(context): _*)
.bindings(
ModuleMock
)
}
}
object ModuleMock extends Module {
def bindings(environment: Environment, configuration: Configuration) = {
Seq(
bind[Lang].toInstance(Lang.defaultLang),
bind[ControllerComponents].toInstance(Helpers.stubControllerComponents()),
...
)
}
}
In the test class, we have
private val app = new MyApplicationBuilder(dbSuffix).build()
private val mockEnv = app.injector.instanceOf(classOf[MockEnvironment])
private def controller(service: AuthorizationService) = {
new MyController(
mockEnv,
service,
app.injector.instanceOf(classOf[StringResources]),
app.injector.instanceOf(classOf[MessagesApi]),
app.injector.instanceOf(classOf[Lang])
)
}
If I try to run it, I get the following error:
[info] com.google.inject.CreationException: Unable to create injector, see the following errors:
[info]
[info] 1) A binding to play.api.mvc.ControllerComponents was already configured at com.dummy.ModuleMock$.bindings(TestUtil.scala:58):
[info] Binding(interface play.api.mvc.ControllerComponents to ProviderTarget(play.api.inject.BindingKey$$anon$1@77bec56c)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1).
[info] at play.api.inject.BuiltinModule$$anonfun$$lessinit$greater$1.apply(BuiltinModule.scala:59):
[info] Binding(interface play.api.mvc.ControllerComponents to ConstructionTarget(class play.api.mvc.DefaultControllerComponents)) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$1)
If I remove the binding from my ModuleMock and create the following:
private class OverridingControllerComponents extends AbstractModule with ScalaModule {
override def configure(): Unit = {
bind[ControllerComponents].toInstance(Helpers.stubControllerComponents())
}
}
And the MyApplicationBuilder is changed to call the OverridingControllerComoments class:
val app = new PureApplicationLoader()
.builder(context)
.overrides(new OverridingEnvironmentModule(pureEnv))
.overrides(new OverridingControllerComponents)
.bindings(bind[LiveDBID].toInstance(dbSuffix))
.build()
All of a sudden, the error is changed to
[info] java.util.NoSuchElementException: ControllerComponents not set! Call setControllerComponents or create the instance with dependency injection.
[info] at play.api.mvc.InjectedController$class.fallbackControllerComponents(Controller.scala:195)
[info] at com.dummy.RestBaseController.fallbackControllerComponents(RestBaseController.scala:16)
[info] at play.api.mvc.InjectedController$class.controllerComponents(Controller.scala:180)
[info] at com.dummy.restbase.RestBaseController.controllerComponents(RestBaseController.scala:16)
[info] at play.api.mvc.BaseController$class.Action(Controller.scala:161)
[info] at com.dummy.restbase.RestBaseController.Action(RestBaseController.scala:16)
[info] at com.dummy.MyController.authorizationCode(Authorization.scala:34)
[info] at com.dummy.MyControllerTest$$anonfun$1$$anonfun$apply$mcV$sp$1.apply(MyControllerTest.scala:52)
[info] at com.dummy.MyControllerTest$$anonfun$1$$anonfun$apply$mcV$sp$1.apply(MyControllerTest.scala:50)
[info] at org.scalatest.OutcomeOf$class.outcomeOf(OutcomeOf.scala:85)
It is as if, it doesn't see that injected ControllerComponents which I find very odd.
Creating an anonymous instance of MyController class with overriding def controllerComponents does work but it's sort of a pain.