I have the following Controller in Play Framework:
final class ProvisioningController(bindings: Bindings[IO],
val controllerComponents: ControllerComponents) extends ControllerBase {
......
......
......
......
}
As you can see I'm using a class called Bindings that contains all the necessary dependencies. I'm not doing any @Inject, but rather managing them by myself through Bindings. Now, I would like to unit test my Controller, so I wanted to use the Play Framework scala test and I have my controller spec like this:
class ProvisioningControllerSpec extends ControllerBaseSpec with Results {
implicit val timeout: Timeout = 5.seconds // Change the duration as needed
"ProvisioningController#appConfig" should {
"should return the active AppConfig as JSON" in {
val controller = new ProvisioningController(bindings.appConfig, Helpers.stubControllerComponents())
val result: Future[Result] = controller.appConfig.apply(FakeRequest())
val bodyText: JsValue = contentAsJson(result)
bodyText mustBe "ok"
}
}
}
When I ran my application, it ran into an error that I could now understand:
[info] 1) No implementation for controllers.impl.ProvisioningController (with no qualifier annotation) was bound, and could not find an injectable constructor. Injectable classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
[info] at controllers.impl.ProvisioningController.class(ProvisioningController.scala:16)
[info] while locating controllers.impl.ProvisioningController
[info] for the 3rd parameter of router.Routes.<init>(Routes.scala:28)
[info] at play.api.inject.RoutesProvider$.bindingsFromConfiguration(BuiltinModule.scala:139):
[info] Binding(class router.Routes to self) (via modules: com.google.inject.util.Modules$OverrideModule -> play.api.inject.guice.GuiceableModuleConversions$$anon$4)
How can I fix this?
I had to instantiate my own FakeApplication by extending the FakeApplicationFactory class like this:
override def fakeApplication(): Application = {
val env = Environment.simple(new File("."))
val context = ApplicationLoader.Context.create(
environment = env,
initialSettings = Map.empty,
lifecycle = new DefaultApplicationLifecycle()
)
new Bootstrap().load(context)
}