使用数据库进行测试:“连接过多"; [英] Play tests with database: "Too many connections"

查看:72
本文介绍了使用数据库进行测试:“连接过多";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要在具有演化的scalatest中提供数据库,我使用默认PlaySpec的扩展名,该扩展名受

To have a database available in scalatest with evolutions I use this extension of the default PlaySpec inspired by this SO question:

trait ResetDbSpec extends PlaySpec with BeforeAndAfterAll {
  lazy val appBuilder = new GuiceApplicationBuilder()
  lazy val injector = appBuilder.injector()
  lazy val databaseApi = injector.instanceOf[DBApi]

  override def beforeAll() = {
    Evolutions.applyEvolutions(databaseApi.database("default"))
  }

  override def afterAll() = {
    Evolutions.cleanupEvolutions(databaseApi.database("default"))
    databaseApi.database("default").shutdown()
  }
}

它在套件开始时应用数据库演化,并在套件结束时恢复数据库演化.然后测试看起来像

It applies database evolutions when the suite starts, and reverts them when the suite ends. A test then looks like

class ProjectsSpec extends ResetDbSpec with OneAppPerSuite { ...

添加了更多这样的测试后,我碰到了一个点,即当我单独运行它们时,某些测试成功了,并由于以下错误而失败:

After adding more tests like this, I hit a point where some tests that succeed when I run them alone, fail with this error:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException:数据源拒绝建立连接,来自服务器的消息:连接太多"

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection, message from server: "Too many connections"

如上面的代码所示,我尝试添加行

As can be see in the code above, I tried to add the line

databaseApi.database("default").shutdown()

中的

可以缓解这种情况,但是没有效果.我尝试不并行运行测试,但也没有任何效果.在不关闭数据库连接的情况下打开数据库连接应该在哪里?应该在哪里调用shutdown()?

N.B.我使用Play 2.5.10和Slick 3.1.

推荐答案

尽管它不能解决连接泄漏的问题,但我终于设法解决了这个问题:

Although it does not answer to what is happening with the connections leakage, I finally managed to hack around this:

  1. jdbc 添加到您的libraryDependencies,即使

  1. Add jdbc to you libraryDependencies, even if the Play-Slick FAQ tells you not to do it:

# build.sbt
libraryDependencies += jdbc

重新启动sbt以考虑更改.在IntelliJ中,您也将要刷新项目.

Restart sbt to take changes into account. In IntelliJ, you will want to refresh the project, too.

禁用与play-slick冲突的 jdbc 模块(信用:此答案):

Disable the jdbc module that is conflicting with play-slick (credits: this SO answer):

# application.conf
play.modules.disabled += "play.api.db.DBModule"

在同一位置,您应该已经配置了

At the same place you should have already configured something like

slick {
  dbs {
    default {
      driver = "slick.driver.MySQLDriver$"
      db.driver = "com.mysql.jdbc.Driver"
      db.url = "jdbc:mysql://localhost/test"
      db.user = "sa"
      db.password = ""
    }
  }
}

  • 现在,您可以使用 jdbc 中的play.api.db.Databases及其方法withDatabase来运行进化.

  • Now you can use play.api.db.Databases from jdbc and its method withDatabase to run the evolutions.

    import org.scalatest.BeforeAndAfterAll
    import org.scalatestplus.play.PlaySpec
    import play.api.db.{Database, Databases}
    import play.api.db.evolutions.Evolutions
    
    
    trait ResetDbSpec extends PlaySpec with BeforeAndAfterAll {
    
      /**
       * Here we use Databases.withDatabase to run evolutions without leaking connections.
       * It slows down the tests considerably, though.
       */
    
      private def withTestDatabase[T](block: Database => T) = {
        Databases.withDatabase(
          driver = "com.mysql.jdbc.Driver",
          url = "jdbc:mysql://localhost/test",
          name = "default",
          config = Map(
            "username" -> "sa",
            "password" -> ""
          )
        )(block)
      }
    
      override def beforeAll() = {
        withTestDatabase { database =>
          Evolutions.applyEvolutions(database)
        }
      }
    
      override def afterAll() = {
        withTestDatabase { database =>
          Evolutions.cleanupEvolutions(database)
        }
      }
    
    }
    

  • 最后,调用需要进行数据库重置的测试,如下所示:

  • Finally, call tests requiring a db reset like this:

    class MySpec extends ResetDbSpec {...}
    

  • 当然,它在"application.test.conf"和withDatabase()中都重复了此配置,而且混合了两种不同的API,而不是在谈论性能.还会在每个套件之前和之后添加此名称,这很烦人:

    Of course it sucks repeating this config both in "application.test.conf" and in withDatabase(), plus it mixes two different APIs, not talking about performance. Also it adds this before and after each suite, which is annoying:

    [info]应用程序-为数据源默认"创建池
    [info]应用程序-关闭连接池.

    [info] application - Creating Pool for datasource 'default'
    [info] application - Shutting down connection pool.

    如果有人有更好的建议,请改进此答案!我已经挣扎了几个月.

    If somebody has a better suggestion, please improve on this answer! I have been struggling for months.

    这篇关于使用数据库进行测试:“连接过多";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆