Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I change Guice bindings for functional tests?

I'm working on a Play (v. 2.4) application with Guice as DI provider. Everything runs fine however I have a set of functional tests running with ScalaTestPlus and I would like to replace some dependencies when the test are running. The tests are written by extending OneServerPerSuite class as they check my REST API.

Is there any way to have other dependencies during tests?

EDIT: Sample code:

Sample controller:

class UserController @Inject()(userService: UserService) extends AbstractController { ... }

And dependecy definition in module:

bind(classOf[UserService]) to (classOf[ProdUserService])

My tests are like this:

class ApiTest extends PlaySpec with OneServerPerSuite {

    "User API should" must {
         "get User's data" in {
             (...) //calling to an endpoint and verifying response
         }
     }
}

I would like to have ProdUserService replaced with other implementation but only in tests.

like image 392
walak Avatar asked Sep 14 '15 18:09

walak


1 Answers

This should do it:

import play.api.test._
import play.api.test.Helpers._
import play.api.inject.bind
import play.api.Application
import play.api.inject.guice.GuiceApplicationBuilder
import database.AccountDAO
import play.api.Configuration
import play.api.Mode

class ApiTest extends PlaySpec with OneServerPerSuite {

 def app = new GuiceApplicationBuilder() // you create your app
        .configure(
          Configuration.from(
            Map( // a custom configuration for your tests only
              "slick.dbs.default.driver" -> "slick.driver.H2Driver$",
              "slick.dbs.default.db.driver" -> "org.h2.Driver",
              "slick.dbs.default.db.connectionPool" -> "disabled",
              "slick.dbs.default.db.keepAliveConnection" -> "true",
              "slick.dbs.default.db.url" -> "jdbc:h2:mem:test",
              "slick.dbs.default.db.user" -> "sa",
              "slick.dbs.default.db.password" -> "")))
        .bindings(bind[UserService].to[UserServiceImpl]) // here you can define your bindings for an actual implementation (note the use of square brackets)
        .in(Mode.Test)
        .build()


    "User API should" must {
         "get User's data" in new WithApplication(app) {
            // if you want to get the controller with everything injected
            val app2controller = Application.instanceCache[controllers.UserController]
            val userController = app2controller(app) // with this you get the controller with the service injected

             (...) //calling to an endpoint and verifying response
         }
     }
}
like image 127
mundacho Avatar answered Nov 11 '22 02:11

mundacho