scalaplayframeworkslickscalatestplay-slick

Injecting PlaySlick database connection in ScalaTest


I have the following DAO that connects to a database using PlaySlick. The class has a method read that I need to test with ScalaTest. My problem is that I don't know how to mock DatabaseConfigProvider to inject it in the UsersDAO class and test the read method. This is the class to test:

class UsersDAO @Inject()(@NamedDatabase("mydb") 
          protected val dbConfigProvider: DatabaseConfigProvider)
          extends with HasDatabaseConfigProvider[JdbcProfile] {

   import driver.api._

   val db1 = dbConfigProvider.get[JdbcProfile].db

   def read (sk: Int) = {
      val users = TableQuery[UserDB]
      val action = users.filter(_.sk === sk).result
      val future = db1.run(action.asTry)
      future.map{
        case Success(s) => 
          if (s.length>0)
            Some(s(0))
          else
            None
        case Failure(e) => throw new Exception ("Failure: " + e.getMessage)
      }
   }

}

and this is my attempt to write the test:

class UserDAOTest extends PlaySpec with OneAppPerSuite  {

  implicit override lazy val app = new GuiceApplicationBuilder().
  configure(
            Configuration.from(
                Map(
                    "slick.dbs.mydb.driver" -> "slick.driver.MySQLDriver$",
                    "slick.dbs.mydb.db.driver" -> "com.mysql.jdbc.Driver",
                    "slick.dbs.mydb.db.url" -> "jdbc:mysql://localhost:3306/control",
                    "slick.dbs.mydb.db.user" -> "root",
                    "slick.dbs.mydb.db.password" -> "xxxxx"
                )
            )
        ).build

  val dbConfigProvider = app.injector.instanceOf[DatabaseConfigProvider]

  "Example " should {
    "be valid" in {

      val controller = new UsersDAO(dbConfigProvider)
      val result = controller.read(1)
      println(result) 
    }
  }

When I run the test it fails with the following error message:

com.google.inject.ConfigurationException: Guice configuration errors:

1) No implementation for play.api.db.slick.DatabaseConfigProvider was bound. while locating play.api.db.slick.DatabaseConfigProvider


Solution

  • IMHO, it is best not to interfere with Play's injection stuff, but to just use it. This should work:

    class UserDAOTest extends PlaySpec with OneAppPerSuite with ScalaFutures {
    
      implicit override lazy val app = new GuiceApplicationBuilder().
        configure(
          "slick.dbs.mydb.driver" -> "slick.driver.MySQLDriver$",
          "slick.dbs.mydb.db.driver" -> "com.mysql.jdbc.Driver",
          "slick.dbs.mydb.db.url" -> "jdbc:mysql://localhost:3306/control",
          "slick.dbs.mydb.db.user" -> "root",
          "slick.dbs.mydb.db.password" -> "xxxxx").build
    
      def userDAO(implicit app: Application): UserDAO = Application.instanceCache[UserDAO].apply(app)
    
      "UserDAO" should {
        "do whatever" in {
          whenReady(userDAO.read(1)) { res =>
            println(res)
          }
        }
      }
    
    }
    

    I've updated my repo in case I missed something.