为每个测试使用不同的内存数据库 运行

Use different in-memory database for every test run

我有一个 Play 应用程序,其中包含一些涉及数据库的测试。为此,我将 Slick 配置为在测试 运行s 期间使用单独的内存中 H2 实例,例如:

slick.dbs.default.db.url="jdbc:h2:mem:play-test"

现在,ScalaTest 并行执行套件,这通常不成问题,因为会为每个套件重新创建 Play 应用程序。但是,它们都接触同一个数据库,可能会导致意外状态并导致测试失败。

在 运行 本地时运行良好,但在 CI 服务器上失败,日志表明测试执行顺序不同,如果不是并行,这本身应该不是问题,但是一次测试开始时的数据库状态不符合预期。

现在,我的一个解决方案是 运行 这些套件依次使用 Sequential

但在我看来,如果仍然能够并行 运行 它们会更好,但是使用不同的数据库,例如:

slick.dbs.default.db.url="jdbc:h2:mem:play-test-${UUID.generate()}"

以上语法完全是编造的,但是 Play 配置文件是否支持 UUID(或其他一些随机字符串)生成?

多亏了,我最终创建了一个特征,用随机后缀自定义我的内存 H2 名称:

trait FreshDatabase extends GuiceOneAppPerSuite {
  this: TestSuite =>

  val BaseName = "play-test"
  val UrlConfigKey = "slick.dbs.default.db.url"

  override def fakeApplication(): Application = {
    val defaultUrl = super.fakeApplication().configuration.get[String](UrlConfigKey)

    val random = Random.nextInt(Integer.MAX_VALUE)
    val freshUrl = defaultUrl.replace(BaseName, s"$BaseName-$random")

    GuiceApplicationBuilder().configure(UrlConfigKey -> freshUrl).build()
  }
}

然后在相关的测试套件中使用它,例如:

class AnswerControllerSpec extends PlaySpec
  with GuiceOneAppPerSuite with FreshDatabase {
  // ...
}

我的application.conf(和以前一样):

slick.dbs.default.profile="slick.jdbc.H2Profile$"
slick.dbs.default.db.driver="org.h2.Driver"
slick.dbs.default.db.url="jdbc:h2:mem:play-test"