Scala 如何使用可配置的数据库将光滑的代码组织成单独的可测试单元?

Scala 如何使用可配置的数据库将光滑的代码组织成单独的可测试单元?,scala,slick,slick-3.0,Scala,Slick,Slick 3.0,我有几个应用程序的代码库,其中有一个共享数据库,使用Slick进行数据库访问。部分代码(如公共表映射)位于公共库中。我希望能够在这些项目上运行两种测试: 使用真实数据库的测试 使用内存中H2数据库的其他测试 为了支持这一点,我尝试了几种组织代码的方法,但总是在某些时候遇到困难。我最近的尝试是使用DatabaseConfig方法,将数据库定义(包括数据库、概要文件和表定义)传递给执行数据库操作的对象(让我们称之为服务)。这样,理论上,我可以通过传入我想要测试的数据库定义来轻松测试服务。实际上,

我有几个应用程序的代码库,其中有一个共享数据库,使用Slick进行数据库访问。部分代码(如公共表映射)位于公共库中。我希望能够在这些项目上运行两种测试:

  • 使用真实数据库的测试
  • 使用内存中H2数据库的其他测试
为了支持这一点,我尝试了几种组织代码的方法,但总是在某些时候遇到困难。我最近的尝试是使用
DatabaseConfig
方法,将数据库定义(包括数据库、概要文件和表定义)传递给执行数据库操作的对象(让我们称之为服务)。这样,理论上,我可以通过传入我想要测试的数据库定义来轻松测试服务。实际上,我在服务之间的交互中遇到问题,因为类型不适合

我创建了一个简化的示例,展示了我遇到的问题:

import slick.basic.DatabaseConfig
import slick.jdbc.JdbcProfile
import slick.lifted.Rep

import scala.concurrent.Future

trait HasProfile {
  val profile: JdbcProfile
}

trait HasId {
  val id: Rep[Long]
}

trait Table_Person {
  this: HasProfile =>

  case class PersonRow(personId: Long, lastName: String)

  import profile.api._

  class Person(tableTag: Tag) extends Table[PersonRow](tableTag, "person") with HasId {
    val personId = column[Long]("person_id", O.PrimaryKey, O.AutoInc)
    val lastName = column[String]("last_name")

    override val id = personId

    val * = (personId, lastName).mapTo[PersonRow]
  }

  lazy val Person = TableQuery[Person]
}

class DatabaseWrapper {
  private val databaseConfig: DatabaseConfig[JdbcProfile] = DatabaseConfig.forConfig("PersonDatabase")

  def db = databaseConfig.db

  object Schema extends HasProfile with Table_Person {
    override val profile = databaseConfig.profile
  }

}

class PersonService(val databaseWrapper: DatabaseWrapper) {

  import databaseWrapper.Schema._

  val loadService = new LoadService(databaseWrapper)

  def load(id: Long): Future[Option[PersonRow]] = loadService.load[PersonRow](Person, id)
}

class LoadService(val databaseWrapper: DatabaseWrapper) {

  import databaseWrapper.Schema.profile.api._

  def load[R](tableQuery: TableQuery[_ <: Table[R] with HasId], id: Long): Future[Option[R]] = databaseWrapper.db.run(tableQuery.filter(_.id === id).result.headOption)
}
import slick.basic.DatabaseConfig
导入slick.jdbc.jdbc配置文件
导入slick.lifted.Rep
导入scala.concurrent.Future
特征轮廓{
val配置文件:JdbcProfile
}
特征哈西德{
val id:Rep[Long]
}
个人特质表{
这个:HasProfile=>
案例类PersonRow(personId:Long,lastName:String)
导入profile.api_
类Person(tableTag:Tag)使用HasId扩展表[PersonRow](tableTag,“Person”){
val personId=列[Long](“person_id”,O.PrimaryKey,O.AutoInc)
val lastName=列[字符串](“姓氏”)
覆盖val id=personId
val*=(personId,lastName).mapTo[PersonRow]
}
lazy val Person=TableQuery[Person]
}
类数据库包装器{
private val databaseConfig:databaseConfig[JdbcProfile]=databaseConfig.forConfig(“PersonDatabase”)
def db=databaseConfig.db
对象架构使用表“”扩展HasProfile{
覆盖val profile=databaseConfig.profile
}
}
类PersonService(val databaseWrapper:databaseWrapper){
导入databaseWrapper.Schema_
val loadService=新的loadService(databaseWrapper)
def load(id:Long):Future[Option[PersonRow]]=loadService.load[PersonRow](个人,id)
}
类LoadService(val databaseWrapper:databaseWrapper){
导入databaseWrapper.Schema.profile.api_
def load[R](tableQuery:tableQuery[\uu]也可以查看(对于“真实”持久性单元测试,不是H2)也可以查看(对于“真实”持久性单元测试,不是H2)
Error:(51, 79) type mismatch;
found   : slick.lifted.TableQuery[PersonService.this.databaseWrapper.Schema.Person]
required: PersonService.this.loadService.databaseWrapper.Schema.profile.api.TableQuery[_ <: PersonService.this.loadService.databaseWrapper.Schema.profile.api.Table[PersonService.this.databaseWrapper.Schema.PersonRow] with HasId]
(which expands to)  slick.lifted.TableQuery[_ <: PersonService.this.loadService.databaseWrapper.Schema.profile.Table[PersonService.this.databaseWrapper.Schema.PersonRow] with HasId]
def load(id: Long): Future[Option[PersonRow]] = loadService.load[PersonRow](Person, id)