gpt4 book ai didi

scala - 使用 Slick 和 Postgres 玩 2.1 单元测试

转载 作者:行者123 更新时间:2023-12-04 20:10:59 36 4
gpt4 key购买 nike

我想使用与生产中使用的相同的数据库设置为 Play 2 Scala 应用程序运行单元测试:Slick with Postgres。以下失败并显示“java.sql.SQLException:试图从已关闭的池中获取连接”。在第二次测试中。

package controllers

import org.specs2.mutable._
import play.api.db.DB
import play.api.Play.current
import play.api.test._
import play.api.test.Helpers._
import scala.slick.driver.PostgresDriver.simple._

class BogusTest extends Specification {

def postgresDatabase(name: String = "default",
options: Map[String, String] = Map.empty): Map[String, String] =
Map(
"db.test.driver" -> "org.postgresql.Driver",
"db.test.user" -> "postgres",
"db.test.password" -> "blah",
"db.test.url" -> "jdbc:postgresql://localhost/blah"
)

def fakeApp[T](block: => T): T =
running(FakeApplication(additionalConfiguration =
postgresDatabase("test") ++ Map("evolutionplugin" -> "disabled"))) {
def database = Database.forDataSource(DB.getDataSource("test"))
database.withSession { implicit s: Session => block }
}

"Fire 1" should {
"do something" in fakeApp {
success
}
}

"Fire 2" should {
"do something else" in fakeApp {
success
}
}
}

我像这样运行测试:
$ play -Dconfig.file=`pwd`/conf/dev.conf "test-only controllers.BogusTest"

另外两个谜团:

1)所有测试都运行,即使我要求只运行 BogusTest

2)总是使用application.conf,而不是def.conf,驱动信息来自application.conf,而不是代码中配置的info。

最佳答案

这是一个暂定的答案,因为我目前已经在 play 2.2.0 上进行了测试,我无法使用 MYSQL 数据库重现您的错误。

我觉得您的代码中可能存在一个非常棘手的错误。首先,如果你探索一下 Play 提供的 DBPlugin 实现,BoneCPPPlugin:

  /**
* Closes all data sources.
*/
override def onStop() {
dbApi.datasources.foreach {
case (ds, _) => try {
dbApi.shutdownPool(ds)
} catch { case NonFatal(_) => }
}
val drivers = DriverManager.getDrivers()
while (drivers.hasMoreElements) {
val driver = drivers.nextElement
DriverManager.deregisterDriver(driver)
}
}

您会看到 onStop() 方法关闭了连接池。所以很明显,您向第二个测试示例提供了一个已经停止的应用程序(因此它的插件被停止并且数据库连接池关闭)。

Scalatests 和 specs2 并行运行测试,您可以依赖测试助手,因为它是线程安全的:
  def running[T](fakeApp: FakeApplication)(block: => T): T = {
synchronized {
try {
Play.start(fakeApp)
block
} finally {
Play.stop()
play.api.libs.ws.WS.resetClient()
}
}
}

然而,当你做
DB.getDataSource("test")

来自Play的源代码:
  def getDataSource(name: String = "default")(implicit app: Application): DataSource = app.plugin[DBPlugin].map(_.api.getDataSource(name)).getOrElse(error)

所以这里有一个隐式的,它没有解析为 FakeApplication(它不是一个隐式的作用域!!!),而是解析为 Play.current并且似乎在第二种情况下,这不是您所期望的,Play.current 仍然指向 FakeApplication 的前一个实例:它可能取决于在闭包中如何捕获隐式

但是,如果您重构 fakeApp 方法,则可以确保您刚刚创建的应用程序用于解析隐式(您始终可以明确隐式参数的值)
  def fakeApp[T](block: => T): T = {
val fakeApplication = FakeApplication(additionalConfiguration =
postgresDatabase("test") ++ Map("evolutionplugin" -> "disabled"))
running(fakeApplication) {
def database = Database.forDataSource(DB.getDataSource("test")(fakeApplication))
database.withSession { implicit s: Session => block }
}
}

关于scala - 使用 Slick 和 Postgres 玩 2.1 单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17286359/

36 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com