Kotlin + JUnit + postgres进行集成测试:泄漏连接

我建立了一个运行13个集成测试的测试课程。 所有的测试都涉及1个数据库,1个模式和3个表格。 测试类的设置是为了使用@BeforeClass创建测试数据库,并使用@AfterClass删除测试数据库。 在每个测试的setUp阶段,我迁移模式并用人工数据填充表格。 然后在tearDown阶段,我删除模式。 在每个测试中,我运行我的测试逻辑对测试数据库:

 class MyTest { companion object { private val helper = MyHelper() @BeforeClass @JvmStatic fun createTestDatabase() { helper.createTestDatabase() } @AfterClass @JvmStatic fun removeTestDatabase() { helper.deleteTestDatabase() } } @Before fun setUp(){ // migrate the schema and populate the tables with artificial data helper.migrate() helper.populate() } @After fun tearDown() { // remove the schema helper.removeSchema() } @Test MyFirstTest() { // populate the tables with artificial data ... // test logic } ... } 

数据库操作全部在MyHelper类中实现。 特别是, MyHelper中有一个执行查询字符串的函数:

 class MyHelper { protected val POSTGRES_USER = "postgres" protected val POSTGRES_HOST = "localhost" protected val POSTGRES_PORT = 5432 protected val POSTGRES_TEST_DATA_DATABASE = "my_database_test" protected val POSTGRES_TEST_DATA_SCHEMA = "my_schema" protected val POSTGRES_DEFAULT_DATABASE = "postgres" protected val POSTGRES_DEFAULT_SCHEMA = "postgres" protected val graphDataTables = listOf("my_table_1", "my_table_2", "my_table_3") val databases = listOf(POSTGRES_DEFAULT_DATABASE, POSTGRES_TEST_DATA_DATABASE) val dataSources = databases.associateBy({it}, { getDataSource(it)}) fun getDataSource(database: String): PGSimpleDataSource { val ds = PGSimpleDataSource() val url = "jdbc:postgresql://$POSTGRES_HOST:$POSTGRES_PORT/$database" ds.setUrl(url) ds.setUser(POSTGRES_USER) return ds } fun executeQuery(sqlQuery: String, database: String = this.POSTGRES_DEFAULT_DATABASE, schema: String = this.POSTGRES_DEFAULT_SCHEMA ): Unit { val ds = dataSources[database]!! ds.currentSchema = schema ds.connection.use { it.createStatement().use { it.execute(sqlQuery) } } } ... } 

函数MyHelper.populate()使用executeQuery函数将数据插入到表中。

我的问题是,似乎我有很多未关闭的连接(泄露的连接)。 如果我把测试数量保持在10以下,那么所有的测试都没有问题。 只要我通过10,我得到如下测试11及以上的错误:

 Nov 09, 2017 11:31:55 AM org.postgresql.Driver connect SEVERE: Connection error: org.postgresql.util.PSQLException: FATAL: sorry, too many clients already at org.postgresql.Driver$ConnectThread.getResult(Driver.java:401) at org.postgresql.Driver.connect(Driver.java:259) ... 

对于10日以后运行的测试。 日志中的最后一个堆栈指向函数executeQueryds.connection.use {行。

但是,如果将helper.createTestDatabase()移出协同对象,并将其放在MyTest的init块中,如下所示:

 class MyTest { companion object { private val helper = MyHelper() } init { helper.createTestDatabase() } ... } 

那么即使我的测试数超过10,我也不会得到任何错误。我看到的问题是,现在我有一个测试数据库在我的postgres docker容器中创建,并且在完成集成测试。 我不知道如何现在调用removeTestDatabase

我在调试模式下运行测试,并在第十次测试中间停止,然后用

 select * from pg_stat_activity; 

我可以看到第一种情况下有很多空闲连接(接近100个)。 在第二种情况下,我在第十次测试中只有10个空闲连接(当然,我想空闲连接的数量为0)。 我的理解是,我的默认postgres设置是, max_connections设置为100.这就是为什么我得到的错误,当我有超过10个测试在第一个场景。 但我不知道如何创建闲置的连接。