Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring MVC - Cleaning the database between tests using Flyway

I use Flyway to manage the state of my DB in my Spring MVC application.

I have it configured in my servlet context XML file exactly as the recommend in their docs

<bean id="flyway" class="org.flywaydb.core.Flyway" init-method="migrate">
    <property name="dataSource" ref="..."/>
    ...
</bean>

<!-- The rest of the application (incl. Hibernate) -->
<!-- Must be run after Flyway to ensure the database is compatible with the code -->
<bean id="sessionFactory" class="..." depends-on="flyway">
    ...
</bean>

I'd like to do two things in my JUnit tests -

  1. Once, before ALL tests, drop and recreate the database and let it re-migrate. This creates a clean database for each test suite.

  2. Before each test, clean all the DB tables. In other frameworks (e.g. RSpec/Rails) I've accomplished this by running DB statements transactionally so they rollback at the end of the test. Not sure what the best practice is in the Spring MVC world.

I have no clue where to really begin with implementing the above, so any guidance is appreciated.

Thanks!

like image 207
user2490003 Avatar asked Jan 30 '17 04:01

user2490003


2 Answers

First, you can clean the database before each test like so:

@Autowired
Flyway flyway;

@Before
public void init(){
   flyway.clean();
   flyway.migrate();
}

Secondly, you can make use of JdbcTestUtils to delete all the rows from tables. You can find the documentation here: JDBC testing support https://docs.spring.io/spring/docs/current/spring-framework-reference/html/integration-testing.html

You can also make use of @Rollback and @Commit to run the test methods transactionally.

@Rollback indicates whether the transaction for a transactional test method should be rolled back after the test method has completed. If true, the transaction is rolled back; otherwise, the transaction is committed (see also @Commit). Rollback semantics for integration tests in the Spring TestContext Framework default to true even if @Rollback is not explicitly declared.

like image 76
Barath Avatar answered Nov 02 '22 11:11

Barath


My team uses SpringBoot. It has Flyway integration built in. Nothing that follows is necessarily SpringBoot dependent, but using SpringBoot does make some of this easier.

For integration testing with Flyway we use Spring Test, along with an in memory H2 database. We use Spring Profiles to define an 'integation test' profile which has the H2 JDBC config. Spring Test classes spin up the container for each test. Thus, each test gets a clean schema created by Flyway to run against. Since, it's all in memory in H2 there is no clean up. There is also no need for transaction shenanigans that may impact the test behavior.

There is a Flyway / Spring Test annotation library if you really want to jump into bed, so to speak, with Flyway in your integration tests.

like image 37
MarkOfHall Avatar answered Nov 02 '22 11:11

MarkOfHall