首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Slick和Postgres播放2.1单元测试

使用Slick和Postgres播放2.1单元测试
EN

Stack Overflow用户
提问于 2013-06-25 06:43:22
回答 1查看 2.8K关注 0票数 5

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

代码语言:javascript
运行
复制
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
    }
  }
}

我像这样运行测试:

代码语言:javascript
运行
复制
$ play -Dconfig.file=`pwd`/conf/dev.conf "test-only controllers.BogusTest"

另外两个谜团:

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

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

EN

回答 1

Stack Overflow用户

发布于 2013-12-19 20:49:18

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

我觉得你的代码中可能有一个非常棘手的bug。首先,如果您研究Play提供的DBPlugin实现,BoneCPPPlugin:

代码语言:javascript
运行
复制
  /**
   * 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连接池关闭)。

Scalatest和specs2并行运行测试,您可以依赖测试助手,因为它是线程安全的:

代码语言:javascript
运行
复制
  def running[T](fakeApp: FakeApplication)(block: => T): T = {
        synchronized {
          try {
            Play.start(fakeApp)
            block
          } finally {
            Play.stop()
            play.api.libs.ws.WS.resetClient()
          }
        }
      }

但是,当你这样做的时候

代码语言:javascript
运行
复制
DB.getDataSource("test")

来自Play的源代码:

代码语言:javascript
运行
复制
  def getDataSource(name: String = "default")(implicit app: Application): DataSource = app.plugin[DBPlugin].map(_.api.getDataSource(name)).getOrElse(error)

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

但是,如果您重构fakeApp方法,则可以确保您刚刚创建的应用程序用于解析隐式参数(您总是可以显式设置隐式参数的值)

代码语言:javascript
运行
复制
  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 }
      }
  }
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17286359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档