我有以下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
答案 0 :(得分:4)
.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
已注入所有依赖项。)