当我 运行 我的测试套件失败并出现 PSQLException: FATAL: sorry, too many clients already
When I run my test suites they fail with PSQLException: FATAL: sorry, too many clients already
我正在为我的 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:致命:抱歉,已经有太多客户了。
我的考虑:我认为这是因为在每个测试套件中都会创建一个新的 Play Guice 应用程序。我也尝试手动关闭所有数据库的连接,但没有解决问题。
我们遇到了同样的问题,所以我们将这 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 {
...
父 class 现在我们可以在 GuiceOneServerPerSuite
和 ConfiguredApp
之间切换:
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 {
...
我知道这有点 hack - 所以我也对更优雅的解决方案感兴趣;)。
你可以把你的数据库实例作为单例,如果你这样做,他不会创建多个实例,因此不会填满连接池。
类似的东西:
@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")
}
希望对您有所帮助。
我正在为我的 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:致命:抱歉,已经有太多客户了。
我的考虑:我认为这是因为在每个测试套件中都会创建一个新的 Play Guice 应用程序。我也尝试手动关闭所有数据库的连接,但没有解决问题。
我们遇到了同样的问题,所以我们将这 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 {
...
父 class 现在我们可以在 GuiceOneServerPerSuite
和 ConfiguredApp
之间切换:
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 {
...
我知道这有点 hack - 所以我也对更优雅的解决方案感兴趣;)。
你可以把你的数据库实例作为单例,如果你这样做,他不会创建多个实例,因此不会填满连接池。
类似的东西:
@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")
}
希望对您有所帮助。