Cedric Reichenbach
Cedric Reichenbach

Reputation: 9319

PlaySpec test class not picked up if using injection

In my Play 2.6.x application, I'm testing with PlaySpec. Now I would like to inject some object to be used in test code.

class AuthControllerTest @Inject()(userRepository: UserRepository)
  extends PlaySpec with GuiceOneAppPerSuite with Injecting {

  "Foo bar" should {
    "do xyz" in {
      // do something with userRepository
    }
  }
}

However, this class never gets picked up for tests, e.g. when running sbt test.

A simple workaround is to manually get the injector from the current Play instance, but Play.current is deprecated and it generally feels hacky:

class AuthControllerTest
  extends PlaySpec with GuiceOneAppPerSuite with Injecting {

  "Foo bar" should {
    "do xyz" in {
      val userRepository = Play.current.injector.instanceOf[UserRepository]
      // do something with userRepository
    }
  }
}

Why doesn't the former example work? And is there a cleaner approach than the latter example?

Upvotes: 3

Views: 783

Answers (1)

marcospereira
marcospereira

Reputation: 12214

Play Framework does not do dependency injection for tests like the first example. On the second one, you don't need Play.current since GuiceOneAppPerSuite makes an Application (app) available to you. So you can do:

val userRepository = app.injector.instanceOf[UserRepository].

And by using Injecting, you can simplify it even further like:

val userRepository = inject[UserRepository]

And from the official docs:

If all or most tests in your test class need an Application, and they can all share the same instance of Application, mix in trait GuiceOneAppPerSuite with the GuiceFakeApplicationFactory trait. You can access the Application from the app field.

There is also a page about Injecting in the official docs.

Upvotes: 3

Related Questions