Spring boot and Flyway: Clear database data before integration tests

This answer was useful but it didn't get me all the way there and so I thought I'd come back and add an answer in case someone else was looking to solve this same issue. The bean definition above was terrific.

There are spring profiles of which there are 5 or so possibilities. I looked at the docs and how people use them but went another route. Maven has 6 scopes, but the ones which are useful in this case are runtime and test.

As I dug into the spring profiles and the various ways one can switch between them it seemed for my situation a bit too complex. I just want my database under test to be created, scructured and populated with some data so I can test the repositories in my jpa spring boot app. I don't want to spend 4 hours setting up profiles. Not that it isn't a worthy endeavor in the long run, just that I wanted to get things moving.

When I execute spring-boot:run, I want the non-test db to be migrated but I don't want any crud data in there that I use for testing.

So, in the live app I want a virtually empty database and during tests, I want flyway to clean the db, run the versioned migrations and populate it with test data.

The answer above led me to a solution which I will probably fold into spring profiles as my project gets closer to production.

Turns out that spring-boot-test provides a @TestConfiguration annotation which you can attach to any class in the src/test/ hierarchy. I created a FlywayConfiguration class which contains the bean definition provided above:

package com.foo.fooservice;

import org.flywaydb.core.Flyway;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.annotation.Bean;

@TestConfiguration
public class FlywayMigrationConfig {

@Bean
public static FlywayMigrationStrategy cleanMigrateStrategy(){

        return flyway -> {
                flyway.clean();
                flyway.migrate();
                };
        }
}

So now, if I want to use this in a test, I add another nifty annotation in the appropriate test class- @Includes, a companion to the @TestConfiguration annotation - so that I can use this configuration in the same way I might have used @BeforeClass like so:

@DataJpaTest
@Import(FlywayMigrationConfig.class) 
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
class AccountUserRepoTest {



    @Autowired 
    private AccountUserRepo accountUserRepo;

    @Autowired
    private FlywayMigrationStrategy strategy;

This allows me to inject this flyway migration strategy on a per-test-class basis. Spring won't auto-inject your bean into every test class and you can use this configuration now just by adding the @Includes annotation to the appropriate test classes. You don't have to define the bean in every test class where you want to use it. Just use @Includes(your@TestCongiguration-annoted-class).

I happen to be using postgresSQL as opposed to H2 because I figure if I'm doing an integration test on the repository entities I might as well do it against what I will be using in production.

Also: src/main/resources has the jdbc and flyway properties set to a dev schema name and jdbc url.

src/test/resources/application.properties sets the schema name to 'test' (you can name it whatever you want).

The one drawback to this approach that you may not want is the granularity- the DB is cleaned and repopulated for every test class which you configure this way.

I personally like this because for each repository class I'm testing I'd like the data to be refreshed. I also like that if I'm working on a particular test class, having the configuration at this level of granularity means that 'run test' works out of the box. No special configuration in the IDE is required to make it work.


You could create configuration file for your tests. It would run one time before all tests.

@Configuration
public class TestConfig {
@Bean
public FlywayMigrationStrategy clean() {
    return flyway -> {
        flyway.clean();
        flyway.migrate();
    };
}
}