在ScalaTest

时间:2016-12-25 13:36:38

标签: scala playframework slick scalatest play-slick

我有以下DAO使用PlaySlick连接到数据库。该类有一个方法read,我需要使用ScalaTest进行测试。我的问题是我不知道如何模拟DatabaseConfigProvider将其注入UsersDAO类并测试read方法。这是要测试的类:

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)
      }
   }

}

这是我尝试编写测试:

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) 
    }
  }

当我运行测试时,它失败并显示以下错误消息:

  

com.google.inject.ConfigurationException:Guice配置   错误:

     

1)play.api.db.slick.DatabaseConfigProvider没有实现   界。找到play.api.db.slick.DatabaseConfigProvider

2 个答案:

答案 0 :(得分:4)

恕我直言,最好不要干扰Play的注射剂,而只是使用它。这应该有效:

.ts

如果我错过了某些内容,我已更新了repo

答案 1 :(得分:3)

我不确定您是想要从测试中完全模拟数据库,还是仅使用不同的数据库配置。

查看代码示例,我假设后者。

如果您真的想在开始时这样做,最简单的解决方案就是:

// instead of your line below
//  val dbConfigProvider = app.injector.instanceOf[DatabaseConfigProvider]
// use this:
   val userDao = app.injector.instanceOf[UsersDao]

上面会注入您的DAO并隐含处理您的DatabaseConfigProvider

但我不明白这一点 - 为什么不在测试资源中创建另一个配置(application.conf),其内容如下:

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"

执行此操作后,只需将app创建更改为:

implicit override lazy val app = new GuiceApplicationBuilder().build

并且通常像这样注入UsersDao(与上面相同):

val usersDao = app.injector.instanceOf[UsersDao]

(我假设您在测试和应用程序中只有不同的数据库配置。)

完整代码

测试/资源/ application.conf

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"

UserDaoTest.scala

import scala.concurrent.Await
import scala.concurrent.duration.DurationInt
//... other imports

class UserDAOTest extends PlaySpec with OneAppPerSuite  {

  implicit override lazy val app = new GuiceApplicationBuilder().build

  val userDao = app.injector.instanceOf[UsersDao]

  "Example " should {
    "be valid" in {
      val result = userDao.read(1)
      println(Await.result(result), 1.second) 

      // would be better to use whenReady from org.scalatest.concurrent.Futures
      // but it's not really related to this question that much
    }
  }
}

<强>摘要

我认为这里的结论是避免手工构建对象(比如第一种方法 - 使用带参数的构造函数创建UsersDao)。如果您不需要这样做(有时您会这样做 - 例如,当您想要更改某些参数时),大多数情况下将整个对象构造委托给DI更容易(比如 - 简单地拉UsersDao已注入所有依赖项。)