Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

H2 in-memory test DB closed, despite 'DB_CLOSE_ON_EXIT=FALSE' [duplicate]

I have some short unit tests that fail with the exception:

javax.persistence.PersistenceException: org.hibernate.exception.GenericJDBCException: could not prepare statement
::
Caused by: org.hibernate.exception.GenericJDBCException: could not prepare statement
::
Caused by: org.h2.jdbc.JdbcSQLException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL) [90121-197]

The source is my Spring Data AuditProvider, specifically this line:

user = entityManager.createNamedQuery("findUserByUsernameAndTenant", User.class)
        .setParameter("tenant", TenantService.DEFAULT_TENANT_ID)
        .setParameter("username", UserService.USER_SYSTEM).getSingleResult();

The Error happens only when executing the whole test suite, not when running this test class only.

Here the TestRunner I'm using etc:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional
@Rollback
public class MyTest {

That's my datasource URL:

spring.datasource.url: 'jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE'

So it seems "DB_CLOSE_ON_EXIT" doesn't solve the problem, any idea what's happening here?

UPDATE:

I just realized, that this happens only when running the tests in Eclipse, but they run through in the command line. While I do get the occasional:

o.s.b.f.support.DisposableBeanAdapter    : Invocation of destroy method failed on bean with name 'inMemoryDatabaseShutdownExecutor': org.h2.jdbc.JdbcSQLException: Database is already closed (to disable automatic closing at VM shutdown, add ";DB_CLOSE_ON_EXIT=FALSE" to the db URL)

but I don't get the PersistenceException and stacktrace.

like image 790
Benjamin Maurer Avatar asked Sep 24 '18 13:09

Benjamin Maurer


People also ask

How do you know if a DB is H2?

Accessing the H2 Console H2 database has an embedded GUI console for browsing the contents of a database and running SQL queries. By default, the H2 console is not enabled in Spring. Then, after starting the application, we can navigate to http://localhost:8080/h2-console, which will present us with a login page.

Is H2 an in memory database?

H2 is an embedded, open-source, and in-memory database. It is a relational database management system written in Java. It is a client/server application. It stores data in memory, not persist the data on disk.

How do I make my H2 database persistent?

If we want to persist the data in the H2 database, we should store data in a file. To achieve the same, we need to change the datasource URL property. In the above property, the sampledata is a file name.


2 Answers

Use DB_CLOSE_DELAY only.

For in-memory database, you shouldn't use DB_CLOSE_ON_EXIT=FALSE: you should only use DB_CLOSE_DELAY=-1. See http://www.h2database.com/html/features.html#in_memory_databases

So you datasource should be:

spring.datasource.url: 'jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1'

It is also possible that your unit tests are executed in parallel processes. Make sure that they all run in the same VM.

If you use Maven, set forkCount to 0:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.22.0</version>
  <configuration>
    <forkCount>0</forkCount>
  </configuration>
</plugin>
like image 133
Olivier Grégoire Avatar answered Sep 28 '22 04:09

Olivier Grégoire


I guess your various unit test classes are all annotated with @RunWith(SpringJUnit4ClassRunner.class) ?

If so, every started test class will boot Spring which will in turn boot JPA. If multiple tests classes are run in parallel, each of them creating, then dropping, the SAME in-memory database, you might have some concurrency issues.

You may also have to set surefire reuseForks parameter to false in order to prevent JUnit from reusing the same 'context' for consecutive tests

like image 41
TacheDeChoco Avatar answered Sep 28 '22 02:09

TacheDeChoco