How to drop in-memory h2db between Spring Integration tests?

This is because each test shares the same database and that the lifecycle of H2 is not in our control. If you start a process (the VM) and require a database named foo, close the application context, start a new one and require foo again you'll get the same instance.

In the upcoming 1.4.2 release we've added a property to generate a unique name for the database on startup (see spring.datasource.generate-unique-name) and that value will be set to true by default on 1.5.

In the meantime, you can annotate each test with @SpringBootTest(properties="spring.datasource.name=xyz") where xyz is different for a test that requires a separate DB.


If I understand everything correctly liquibase takes care of database status. For every file, also for the test data, liquibase creates a checksum in a table to check whether something has changed or not. The h2 instance still alive after a @DirtiesContext so the checksums still exists in the database. Liquibase thinks that everything is correct but the test data may have changed.

To force liquibase to drop the database and recreate a completely new database you must set the properties in application.yml (that one for tests):

liquibase:
    contexts: test
    drop-first: true

or as an alternative you can hardcode it:

liquibase.setDropFirst(true);

You can either annotate your test with @DirtiesContext, which slows down the test because the whole application context gets rebuild.

Or you can create a custom TestExecutionListener which is much faster. I've created a custom TestExecutionListener, which recreates the database and keeps the context.

public class CleanUpDatabaseTestExecutionListener
    extends AbstractTestExecutionListener {

    @Inject
    SpringLiquibase liquibase;

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

    @Override
    public void afterTestClass(TestContext testContext) throws Exception {
        //This is a bit dirty but it works well
        testContext.getApplicationContext()
            .getAutowireCapableBeanFactory()
            .autowireBean(this);
        liquibase.afterPropertiesSet();
    }

if you are using the TestExecutionListener you must add this Listener to your test with:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest
@TestExecutionListeners(listeners = {
    DependencyInjectionTestExecutionListener.class,
    TransactionalTestExecutionListener.class,
    CleanUpDatabaseTestExecutionListener.class,
})
public class Test {
    //your tests
}

NOTE: DO NOT USE @DirtiesContext and the TestExecutionListener together, this will lead to an error.