创建 DatabaseConfigProvider 的实现

Creating Implementation of DatabaseConfigProvider

我正在尝试在无需启动的情况下测试 Slick Play 应用程序,并且 运行 通过 Play 应用程序上下文(使用 H2)进行所有操作。这是因为我想共享 H2 连接并事先做很多测试数据库准备工作。

为此,我需要一个 DatabaseConfigProvider 实现。在这种情况下,我需要一个 JdbcProfile 配置。我要扩展的特征是:

trait DatabaseConfigProvider {
  def get[P <: BasicProfile]: DatabaseConfig[P]
}

但是,我无法获得DatabaseConfigProvider的类型检查方法的签名。

class TestDbProvider(config:DatabaseConfig[JdbcProfile]) extends DatabaseConfigProvider {
  def get[P <: BasicProfile]: DatabaseConfig[P] = config
}

以上实现和许多其他变体都失败了。

[error] RepositoryTest.scala:78: type mismatch;
[error]  found   : slick.backend.DatabaseConfig[slick.driver.JdbcProfile]
[error]  required: slick.backend.DatabaseConfig[P]
[error]     def get[P <: BasicProfile]: DatabaseConfig[P] = config
[error]                                                     ^
[error] one error found
[error] (api/test:compileIncremental) Compilation failed

更多不良变体:

// Fails
class TestDbProvider(config:DatabaseConfig[JdbcProfile]) extends DatabaseConfigProvider {
  def get[P <: BasicProfile]: DatabaseConfig[JdbcProfile] = config
}

// Fails
class TestDbProvider[P <: BasicProfile](config:DatabaseConfig[P]) extends DatabaseConfigProvider {
  def get[P]: DatabaseConfig[P] = config
}

// Fails
class TestDbProvider(config:DatabaseConfig[JdbcProfile]) extends DatabaseConfigProvider {
  def get[JdbcProfile]: DatabaseConfig[JdbcProfile] = config
}

Scala 中实现 DatabaseConfigProvider 的诀窍是什么?查看Slick/Play的代码库,没有这样具体实现的例子。

无论如何,我们无法在不使用转换的情况下完成这项工作。这是我的实现:

def toProvider(dbIn: PostgresDriver.backend.DatabaseDef) = {

    new DatabaseConfig[JdbcProfile] {

      override def db: JdbcProfile#Backend#Database = dbIn
      override def config: Config = None.orNull // unused
      override def driverIsObject: Boolean = true
      override def driverName: String = "org.postgresql.Driver"
      override val driver: JdbcProfile = ExtendedPostgresDriver
    }

    new DatabaseConfigProvider {
      // Cast is necessary, otherwise cannot get to compile
      override def get[P <: BasicProfile]: DatabaseConfig[P] = config.asInstanceOf[DatabaseConfig[P]]
    }
}