Spring tests are closing embedded database multiple times

7.7k views Asked by At

I am using h2 embedded database which is defined like that:

<jdbc:embedded-database id="embeddedDatasource" type="h2"/>

And I have two tests:

@RunWith(SpringJunit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration("classpath:h2-context.xml")
class Test1 {...}

@RunWith(SpringJunit4ClassRunner.class)
@ContextConfiguration("classpath:h2-context.xml")
class Test2 {...}

After all tests execution I do see in the log:

* Closing org.springframework.context.support.GenericApplicationContext
* Closing org.springframework.web.context.support.GenericWebApplicationContext
* Closing JPA EntitiManagerFactory for Persistance unit ...
* Closing JPA EntitiManagerFactory for Persistance unit ...

So, the entity manager is closed for each context after all tests execution. I know that spring caches context files, so I guess h2 bean is shared across two tests.

The problem is: sometimes I get weird exception like:

H2EmbeddedDatabaseConfigurer: Could not shutdown embedded database
jrg.h2.jdbc.JDBCSQLException: The database has been closed [90098-179]

How could I fix that?

This is what I've found so far: Spring’s embedded H2 datasource and DB_CLOSE_ON_EXIT

1

There are 1 answers

1
Sam Brannen On BEST ANSWER

Since you are using Spring Framework 3.1.4, you are potentially seeing the results of a clash between Spring and H2 both attempting to shut down the database.

This conflict has been addressed in Spring Framework 4.0.3 (see SPR-11573 for details).

Specifically, as of Spring 4.0.3, embedded H2 databases are created with the connection URL: "jdbc:h2:mem:%s;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false". The "%s" is the name of the database (e.g., "testdb").

Thus, if you would like the same behavior for your embedded H2 database on versions of Spring prior to 4.0.3, you will need to manually create the DataSource using a connection URL similar to the one above.

So, the entity manager is closed for each context after all tests execution. I know that spring caches context files, so I guess h2 bean is shared across two tests.

Yes, the Spring TestContext Framework caches ApplicationContexts across tests and test classes. But... the DataSource for the embedded H2 database is not shared across those contexts. Rather, in the scenario you've outlined above, you end up with 2 DataSources -- one in each context and both referring to the same in-memory database.

Sooo, now that I think about it, the problem you are encountering is more likely due to the fact that both of your ApplicationContexts are attempting to shut down the exact same in-memory database. To solve that problem, you can consider defining a unique name for the embedded database, each time it's created. For details on this topic, please read the following to JIRA issues which have been resolved for Spring 4.2 but still contain tips on how to achieve the same goals before 4.2.

Regards,

Sam