Solution
Implementation
class JpaDatabaseCleanerExtension : AfterEachCallback {
private lateinit var tableNames: List<String>
override fun afterEach(context: ExtensionContext?) {
if (context == null) {
throw IllegalStateException("No extension context found")
}
if (!this::tableNames.isInitialized) {
SpringExtension.getApplicationContext(context).getBean(EntityManager::class.java)
.also { entityManager -> entityManager.initTableNames() }
}
SpringExtension.getApplicationContext(context).getBean(DataSource::class.java)
.also { dataSource ->
dataSource.connection.use { connection ->
connection.prepareStatement("SET REFERENTIAL_INTEGRITY FALSE").executeUpdate()
tableNames.forEach { name -> connection.prepareStatement("TRUNCATE TABLE $name").executeUpdate() }
connection.prepareStatement("SET REFERENTIAL_INTEGRITY TRUE").executeUpdate()
}
}
}
private fun EntityManager.initTableNames() {
tableNames = metamodel.managedTypes
.mapNotNull { it.javaType.kotlin.findAnnotation<Table>() }
.map { table -> table.name }
}
}
Usage
@ExtendWith(JpaDatabaseCleanerExtension::class)
@AutoConfigureMockMvc
@SpringBootTest
class ArticleFavoriteIntegrationTest(
@Autowired private val mockMvc: MockMvc,
) {
@Test
fun `when post get delete articles favorite expect return valid response`() {
// testcodes
}
}
Reference
- Do not use transactional in tests
- Cleaning up database tables after each integration test method with spring boot 2 and kotlin
- Test case is not represents real applications transaction scope · Issue #33 · raeperd/realworld-springboot-kotlin
- How To Clean Your Database Between JUnit 5 Tests With Spring Boot | Kotlin Tutorial - YouTube