【问题标题】:Use different in-memory database for every test run每次测试运行使用不同的内存数据库
【发布时间】:2018-06-27 07:02:49
【问题描述】:

我有一个 Play 应用程序,其中包含一些涉及数据库的测试。为此,我将 Slick 配置为在测试运行期间使用单独的内存 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(或其他一些随机字符串)生成吗?

【问题讨论】:

  • 如果可以放一个最小的测试示例,那可能会有所帮助。无论如何,您可以使用GuiceApplicationBuilder 动态地configure the application。只需 override fakeApplication 来自 trait GuiceOneAppPerSuite 的方法即可。

标签: playframework slick scalatest


【解决方案1】:

感谢marcospereira's comment,我最终创建了一个特征,用随机后缀自定义了我的 in-mem 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"

【讨论】:

    猜你喜欢
    • 2014-02-19
    • 1970-01-01
    • 1970-01-01
    • 2013-11-08
    • 2023-01-22
    • 2013-06-13
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    相关资源
    最近更新 更多