Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Functional Tests in Play 2.4.6 when using compile time DI

I'm using Play 2.4.6 with compile time dependency injection and ScalaTest. The controller's constructor has few parameters, and in an ApplicationLoader I create it. Here is the code:

class BootstrapLoader extends ApplicationLoader {
  def load(context: Context) = {
    new AppComponents(context).application
  }
}

class AppComponents(context: Context) extends BuiltInComponentsFromContext(context) with NingWSComponents {
  lazy val router = new Routes(httpErrorHandler, authenticationController, applicationController, assets)
  lazy val applicationController = new controllers.Application()
  lazy val authenticationController = new controllers.Authentication()(configuration, wsApi.client)
  lazy val assets = new controllers.Assets(httpErrorHandler)
}

class Authentication(implicit configuration: Configuration, val ws: WSClient) extends Controller {
  def login = Action { implicit request =>
    Unauthorized(s"${redirectUrl}")
  }
}

class AuthenticationSpec extends PlaySpec with OneAppPerSuite {

  implicit val configuration: Configuration = app.configuration
  implicit val wsClient: WSClient = WS.client(app)

  "when user not logged-in" should {
    "return Status code Unauthorized(401) with redirect url" in  {
      1 mustEqual 2
    }
  }
}

When I'm running the test I'm getting the following error:

[info] Exception encountered when attempting to run a suite with class name: controllers.AuthenticationSpec *** ABORTED ***
[info]   com.google.inject.ProvisionException: Unable to provision, see the following errors:
[info] 
[info] 1) Could not find a suitable constructor in controllers.Authentication. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.
[info]   at controllers.Authentication.class(Authentication.scala:19)
[info]   while locating controllers.Authentication
[info]     for parameter 1 at router.Routes.<init>(Routes.scala:35)
[info]   while locating router.Routes
[info]   while locating play.api.test.FakeRouterProvider
[info]   while locating play.api.routing.Router
[info] 
[info] 1 error
[info]   at com.google.inject.internal.InjectorImpl$2.get(InjectorImpl.java:1025)
[info]   at com.google.inject.internal.InjectorImpl.getInstance(InjectorImpl.java:1051)
[info]   at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:321)
[info]   at play.api.inject.guice.GuiceInjector.instanceOf(GuiceInjectorBuilder.scala:316)
[info]   at play.api.Application$class.routes(Application.scala:112)
[info]   at play.api.test.FakeApplication.routes(Fakes.scala:197)
[info]   at play.api.Play$$anonfun$start$1.apply$mcV$sp(Play.scala:90)
[info]   at play.api.Play$$anonfun$start$1.apply(Play.scala:87)
[info]   at play.api.Play$$anonfun$start$1.apply(Play.scala:87)
[info]   at play.utils.Threads$.withContextClassLoader(Threads.scala:21)

FakeApplication use GuiceApplicationBuilder, which of course does not work.

What should I do to run such tests?

Thanks

like image 522
roterl Avatar asked Jan 05 '16 21:01

roterl


1 Answers

override implicit lazy val app = new BootstrapLoader().load(
ApplicationLoader.createContext(
  new Environment(
    new File("."), ApplicationLoader.getClass.getClassLoader, Mode.Test)))

It works in Play 2.5.1

like image 63
harrylaou Avatar answered Nov 15 '22 10:11

harrylaou