0
votes

I'm implementing an integration test suite in a Spring Boot project. My project is using Flyway for database migration.

My test class looks similar to this:

@SpringBootTest
@AutoConfigureMockMvc
@Testcontainers
internal class MyIntegrationTest {
    @Container
    private val postgres = postgresContainer

    @Autowired
    private lateinit var mockMvc: MockMvc

    // ... several test cases
}

Spring Boot runs Flyway migration at application context startup. The problem is that @SpringBootTest starts application context only once, so my DB is initialized only before all tests and not before each test.

I also tried injecting a Flyway field in my test class:

@Autowired
private lateinit var flyway: Flyway

@BeforeEach
fun setup() {
    flyway.migrate()
}

but there is No qualifying bean of type 'org.flywaydb.core.Flyway' available.

So, which is the right way to trigger migration before each test?

NOTES:

  • (PostgreSQL) test container is correctly created and started for each single test.
  • I'm using this config in application.properties: spring.flyway.enabled=false
2
Have a look at the Flyway test extensions - Dirk Deyne
Injecting a flyway field and running flyway.clean(), flyway.migrate() should work. Have you inspected why it can't find a qualifying bean? - Onome Sotu
@OnomeSotu, yes, you're right. I was using a wrong config for Flyway... - davioooh

2 Answers

2
votes

Found a solution thinkering with JUnit and Spring Boot configuration.

The reason for No qualifying bean of type 'org.flywaydb.core.Flyway' available was my wrong configuration: spring.flyway.enabled=false. This is disabling also the creation of a Flyway instance, not only the initial migration.

So I removed this property from application.properties, and added this code to my test class (as also suggested by Onome Sotu in his comment):

@Autowired
private lateinit var flyway: Flyway

@BeforeEach
fun setup() {
    flyway.clean()
    flyway.migrate()
}

I also added @TestInstance(TestInstance.Lifecycle.PER_CLASS) to the test class: this way the container is created and started just once (no need to recreate the database from scratch now that I can clean it before each test). Additionally, this makes tests execution very faster.

NOTE: Actually, with this setup, container creation is executed twice: one at context startup and one on test class creation. Similarly, DB migration is executed for each test case +1 (the +1 happens at context startup). I'd like to find a way to disable unnecessary container creation and database migration)...

0
votes

Try annotating your tests like this:

@Test
@FlywayTest
public void testFunction(){..}

From Flyway documentation:

Annotation FlywayTest for database unit testing. Use Flyway feature.

clean - execution of flyway task clean
init - execution of flyway task init
migrate - execution of flyway task migrate

https://github.com/flyway/flyway-test-extensions

Also, make sure to include the following dependencies:

testCompile 'org.flywaydb:flyway-core:6.4.1'

testCompile 'org.flywaydb.flyway-test-extensions:flyway-spring-test:6.3.3'