加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 用光滑和Postgres播放2.1单元测试

发布时间:2020-12-16 18:38:28 所属栏目:安全 来源:网络整理
导读:我想使用与生产中使用的相同的数据库设置为Play 2 Scala应用程序运行单元测试:与Postgres一起使用Slick.以下操作失败,出现“java.sql.SQLException:尝试从已关闭的池中获取连接”.在第二次测试. package controllersimport org.specs2.mutable._import pla
我想使用与生产中使用的相同的数据库设置为Play 2 Scala应用程序运行单元测试:与Postgres一起使用Slick.以下操作失败,出现“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,而不是代码中配置的信息.

解决方法

这是一个试探性的答案,因为我目前在Play 2.2.0上测试过,我无法使用MYSQL数据库重现您的错误.

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

/**
   * 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()方法关闭连接池.所以很明显,您要向第二个测试示例提供一个已经停止的应用程序(因此它的插件已停止并且db connectin池已关闭).

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 }
      }
  }

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读