【问题标题】:When I run my test suites they fail with PSQLException: FATAL: sorry, too many clients already当我运行我的测试套件时,它们因 PSQLException 失败:致命:抱歉,已经有太多客户端了
【发布时间】:2019-04-02 15:11:32
【问题描述】:

我正在为我的 Play 应用程序编写测试,我想在真实服务器上运行它们,这样我就可以伪造来自外部服务的所有答案。

为了做到这一点,我扩展了 PlaySpec 和 GuiceOneServerPerSuite,并重写了 fakeApplication 方法来创建我的路由并将它们提供给 Guice 应用程序

class MySpec extends PlaySpec with GuiceOneServerPerSuite {

  override def fakeApplication(): Application =
    GuiceApplicationBuilder().appRoutes(app => {
        case ("POST", "/url/") => app.injector.instanceOf(classOf[DefaultActionBuilder]) { Ok }
      }).globalApp(true).build()


  "Something" should {
    "work well" in {
      val wsClient = app.injector.instanceOf[WSClient]
      val service = new MyService(wsClient)
      service.method() mustBe ""

      app.injector.instanceOf[DBApi].databases().foreach(_.getConnection().close())
    }
  }
}

我有多个像这样的测试套件,如果我单独运行它们,它们工作正常,但如果我一起运行它们,它们会填满连接池,然后一切都失败了:org.postgresql.util.PSQLException: FATAL:抱歉,已经有太多客户了。

我的考虑:我认为这是因为在每个测试套件中都会创建一个新的 Play Guice 应用程序。我也尝试手动关闭所有数据库的连接,但没有解决问题。

【问题讨论】:

    标签: scala playframework


    【解决方案1】:

    我们遇到了同样的问题,因此我们将这 2 个用例分开(运行全部或只运行一个测试套件)。

    这使得运行所有测试的速度更快 - 因为 Play Environment 只启动一次。

    套件看起来像:

    class AcceptanceSpecSuite
      extends PlaySpec
        with GuiceOneAppPerSuite
        with BeforeAndAfter {
    
      // all specs
      override def nestedSuites: immutable.IndexedSeq[AcceptanceSpec] = Vector(
        // api
        new DatabaseTaskSpec,
        new HistoryPurgeTaskSpec,
      ...
      )
    
    
      override def fakeApplication(): Application =
        // your initialization
    }
    

    现在每个规范看起来像:

    @DoNotDiscover // important that it is run only if called explicitly
    class DatabaseTaskSpec extends AcceptanceSpec {
    ...
    

    Parent 类现在我们可以在GuiceOneServerPerSuiteConfiguredApp 之间切换:

    trait AcceptanceSpec
      extends PlaySpec
         you need:
        // with GuiceOneServerPerSuite // if you want to test only one Test
        with ConfiguredApp // if you want to test all
        with Logging
        with ScalaFutures
        with BeforeAndAfter {
    ...
    

    我知道这有点小技巧 - 所以我也对更优雅的解决方案感兴趣;)。

    【讨论】:

    • 感谢您的回答和分享您的代码!我尝试了该解决方案,效果很好,但在我的情况下,我还希望每个测试都有不同的路线
    【解决方案2】:

    您可以将您的数据库实例作为单例,如果您这样做,他将不会创建多个实例,因此不会填充连接池。

    类似的东西:

    @Singleton
    object TestDBProperties extends DBProperties {
      override val db: Database = Database.forURL(
        url = "jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=FALSE;",
        driver = "org.h2.Driver")
    }
    

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2012-12-12
      • 1970-01-01
      • 2018-06-20
      • 2011-02-14
      • 2019-06-18
      • 2020-07-05
      • 2018-04-18
      • 2019-05-21
      相关资源
      最近更新 更多