Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setup Spring Boot to close connection pool after @JdbcTest class?

We have large system using Postgresql DB, with rather complex database structure. And we have many DB-related integration tests for that system. Because of the complex DB structure and usage of postres specific sql in code, mocking postgres with H2 (or other in memory DB) seems highly unreliable.

So, we are using junit tests of the following structure:

@RunWith(SpringRunner.class)
@JdbcTest
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
@Sql( ... schema creation, sample data, etc  )
@ContextConfiguration(classes = ... dao and service classes used in the test)

Everything is OK, when you have 2-3 test classes. Problems start to arise when you have 10+ test classes. As I understand it, SpringBoot creates separate connection pool for every distinct context configuration. To keep tests isolated as much as possible, we usually include in context configuration only components, that are used inside the test. So SpringBoot creates dozens of connection pools, that leads to "too many connection"-type errors from connection pool or jdbc driver. You can run your tests one by one, but you cannot run them all at once (so, say farewell to CI).

We are using the following workaround. The following snippet is copy-pasted to every test class:

// <editor-fold name='connection leaking fix'
@Autowired
private DataSource dataSource;
private static HikariDataSource hikariDataSource;

@Before
public void saveDataSource() {
    this.hikariDataSource = (HikariDataSource)dataSource;
}

@AfterClass
public static void releaseDataSource() {
    if (hikariDataSource != null) {
        hikariDataSource.close();
    }
}
// </editor-fold>

It works, but you have to remember that you shouldn't paste that snippet to test classes that use the same context configuration.

The question - is there any way to tell spring boot to close connection pool after each test class execution, or any way to limit number of connection pools spring boot creates?

like image 399
TMTH Avatar asked Mar 23 '18 08:03

TMTH


People also ask

Do we need to close connection in connection pool?

Instead of opening and closing connections for every request, connection pooling uses a cache of database connections that can be reused when future requests to the database are required.

How do I reset my connection pool?

Use the flush-connection-pool in remote mode to reinitialize all connections established in the specified connection pool. The JDBC connection pool or connector connection pool is reset to its initial state.

Do we need to close connection in spring boot?

If you look inside the source, you will see every execute or query closes it resultSet and connection so you do not need to manually close them.

How does Spring Boot manage connection pooling?

The default connection pool in Spring Boot 2 is HikariCP. It provides enterprise-ready features and better performance. HikariCP is a JDBC DataSource implementation that provides a connection pooling mechanism. If the HikariCP is present on the classpath, the Spring Boot automatically configures it.


1 Answers

@M.Deinum is right, the only way to solve the problem without hacking some workaround is to use limited number of configurations. So you can use something like this to test just DAO layer:

@RunWith(SpringRunner.class)
@JdbcTest(includeFilters = @ComponentScan.Filter(Repository.class))
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
@Sql(...)

or that something like this to test DAO and service layer:

@RunWith(SpringRunner.class)
@JdbcTest(includeFilters = {
    @ComponentScan.Filter(Repository.class),
    @ComponentScan.Filter(Service.class)
})
@AutoConfigureTestDatabase(replace= AutoConfigureTestDatabase.Replace.NONE)
@Sql(...)
like image 130
TMTH Avatar answered Oct 12 '22 03:10

TMTH