【发布时间】:2013-08-19 02:39:34
【问题描述】:
我们正在使用 Scala 2.10.2,并且我们将 Slick 1.0.1 用于我们的 DAO。我们正在尝试使用ScalaMock 模拟 DAO,我正在尝试找出一种注入模拟 DAO 的好方法。我已经使用 Java 好几年了,但我两周前才开始使用 Scala。
现在我们的代码看起来像(忽略任何语法错误,我已经压缩了代码,但没有确保它仍然满足类型系统)
abstract class RichTable[T](name: String)
extends slick.driver.MySQLDriver.simple.Table[T](name) {
type ItemType = T
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
...
}
object Users extends RichTable[User]("users") {
def crypted_password = column[String]("crypted_password")
...
}
case class User(id: Option[Int] = None, crypted_password: String) {
def updatePassword(...) = {
Users.where(_.id === id).map{e => e.crypted_password}.update("asdf")
}
}
所有的 DAO 都是继承自 RichTable[T] 的单例对象
我们希望能够模拟用户和其他单例 DAO 对象 - 现在我们所有的单元测试都在访问数据库。然而,我们遇到的问题是如何注入模拟单例对象。到目前为止,我们提出的解决方案是:
object DAORepo {
var usersDAO : Users.type = Users
var anotherDAO : Another.type = Another
...
}
object Users extends RichTable[User]("users") {
def apply() : Users.type = DAORepos.usersDAO
}
def updatePassword(...) = {
Users().where(_.id === id).map{e => e.crypted_password}.update("asdf")
}
def test = {
val mockUsers = mock[Users]
DAORepo.usersDAO = mockUsers
// run test using mock repo
}
我们将所有引用从 Users 更改为 Users(),这不会增加过多的混乱。但是,在 DAORepo 中使用 vars 的味道很糟糕,我想知道是否有人有改进的建议。
我读过 Real-World Scala: Dependency Injection (DI) 和 Component Based Dependency Injection in Scala - 我想我了解如何使用特征来编写 DAORepo,类似于
trait UsersRepo {
val usersDAO : Users.type = Users
}
trait DAORepo extends UsersRepo with AnotherRepo { }
trait UsersTestRepo {
val usersDAO : Users.type = mock[Users]
}
但我仍然不明白如何注入新特性。我可以做类似的事情
class DAORepoImpl extends DAORepo { }
object DAOWrapper {
var repo : DAORepo = new DAORepoImpl
}
def test = {
DAOWrapper.repo = new DAORepoImpl with UsersTestRepo
}
它将object DAORepo 中的两打变量替换为object DAOWrapper 中的一个变量,但似乎应该有一种没有任何变量的干净方法。
【问题讨论】:
-
感谢蛋糕模式的赏金和祝你好运 :) 这并不难,但缺乏很好的资源可以向以前的 java 用户解释它
-
Sebastien Lorber 谢谢,您的 Spring 示例对您有很大帮助
标签: scala dependency-injection mocking