6
votes

I am using Play 2.5.10, Play-slick 2.0.2, and my activator-generated project comes with scalatest and code like this:

class TestSpec extends PlaySpec with OneAppPerSuite {...}

I managed to test routes/Actions; now I would test DAO methods on a lower level. I searched the web and SO for a solution, and could not find any that is still up-to-date. A DAO signature is like this:

class TestDAO @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile]

so I need to pass it the dbConfigProvider thing. For some reason I can't inject the provider into the tests like we do in controllers (no error, tests just won't run):

class TestSpec @Inject()(dbConfigProvider: DatabaseConfigProvider) extends PlaySpec with OneAppPerSuite {...}

The Play-Slick docs say we can alternatively use a global lookup

val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)

but it won't work directly because

There is no started application

and link to an example project doing that:

class TestDAOSpec extends Specification {
  "TestDAO" should {
    "work as expected" in new WithApplicationLoader {   // implicit 'app'
      val app2dao = Application.instanceCache[TestDAO].apply(app)

but I could never find the WithApplicationLoader. Instead, there seems to be a WithApplication:

class TestDAOSpec extends Specification {
  "TestDAO" should {
    "work as expected" in new WithApplication() {   // implicit 'app'
      val app2dao = Application.instanceCache[TestDAO].apply(app)

but then I get

Type mismatch: expected a play.api.Application, got: play.Application.

At this point I lost hope.

How can I test a DAO?

N.B. I don't need to switch databases for testing (I handle this via config), I just want to access the default database in tests.

1
You just need an application in scope, so mix in a OneAppPerSuite or OneAppPerTest. See here.insan-e
I do with OneAppPerSuite, yet I get this. One solution I found was to import play.api.Play.current in the WithApplication() version, then it works but I get a deprecation warning.JulienD
It worked with that example, thanks a lot. I overrid PlaySpec to include all that mysterious mess. I am totally disgusted by how this is so incredibly complicated. Override the implicit app that comes from nowhere, GuiceApplicationBuilder, repeat the conf you already have in your config for no apparent reason, instanceCache, whaaat?? And if I can copy and paste that after sooo many hours trying everything else, why is that not already in the framework???JulienD

1 Answers

2
votes

You can use:

lazy val appBuilder: GuiceApplicationBuilder = new GuiceApplicationBuilder().in(Mode.Test) 
lazy val injector: Injector = appBuilder.injector()
lazy val dbConfProvider: DatabaseConfigProvider = injector.instanceOf[DatabaseConfigProvider]