Set up postgresql testcontainers
- add .json to .editorconfig - add spring-configuration-metadata.json - update README.md - add testcontainers dependencies - add PostgresContainer - add PostgresInitializer
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
package ltd.hlaeja.test.container
|
||||
|
||||
import org.junit.jupiter.api.extension.ExtendWith
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
|
||||
@Suppress("unused")
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@ExtendWith(PostgresExtension::class)
|
||||
@ContextConfiguration(initializers = [PostgresInitializer::class])
|
||||
annotation class PostgresContainer
|
||||
@@ -0,0 +1,74 @@
|
||||
package ltd.hlaeja.test.container
|
||||
|
||||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import org.junit.jupiter.api.extension.AfterAllCallback
|
||||
import org.junit.jupiter.api.extension.BeforeAllCallback
|
||||
import org.junit.jupiter.api.extension.ExtensionContext
|
||||
import org.springframework.core.io.ClassPathResource
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import io.r2dbc.spi.Connection
|
||||
import io.r2dbc.spi.ConnectionFactory
|
||||
import kotlinx.coroutines.reactive.awaitFirstOrElse
|
||||
import kotlinx.coroutines.reactive.awaitFirstOrNull
|
||||
|
||||
class PostgresExtension : BeforeAllCallback, AfterAllCallback {
|
||||
|
||||
override fun beforeAll(context: ExtensionContext) {
|
||||
executeSqlFile(context, "postgres/data.sql")
|
||||
}
|
||||
|
||||
override fun afterAll(context: ExtensionContext) {
|
||||
executeSqlFile(context, "postgres/reset.sql")
|
||||
}
|
||||
|
||||
private fun executeSqlFile(
|
||||
context: ExtensionContext,
|
||||
resourceSourcePath: String,
|
||||
) = runBlocking {
|
||||
if (ClassPathResource(resourceSourcePath).exists()) {
|
||||
executeSqlStatements(
|
||||
postgresConnection(context),
|
||||
makeSqlStatements(ClassPathResource(resourceSourcePath)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("TooGenericExceptionThrown")
|
||||
private suspend fun postgresConnection(
|
||||
context: ExtensionContext,
|
||||
) = SpringExtension.getApplicationContext(context)
|
||||
.getBean(ConnectionFactory::class.java)
|
||||
.create()
|
||||
.awaitFirstOrElse { throw RuntimeException("Connection factory could not be created") }
|
||||
|
||||
private suspend fun executeSqlStatements(
|
||||
connection: Connection,
|
||||
statements: List<String>,
|
||||
) {
|
||||
try {
|
||||
statements.forEach { statement ->
|
||||
connection.createStatement(statement)
|
||||
.execute()
|
||||
.awaitFirstOrNull()
|
||||
}
|
||||
} finally {
|
||||
connection.close().awaitFirstOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeSqlStatements(
|
||||
classPathResource: ClassPathResource,
|
||||
): List<String> = classPathResource.inputStream.use { inputStream ->
|
||||
BufferedReader(InputStreamReader(inputStream))
|
||||
.lines()
|
||||
.filter { it.isNotEmpty() && !it.startsWith("--") }
|
||||
.map { it.trim() }
|
||||
.toList()
|
||||
.joinToString(" ")
|
||||
.split(';')
|
||||
.filter { it.isNotBlank() }
|
||||
.map { "${it.trim()};" }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package ltd.hlaeja.test.container
|
||||
|
||||
import org.springframework.boot.test.util.TestPropertyValues
|
||||
import org.springframework.context.ApplicationContextInitializer
|
||||
import org.springframework.context.ConfigurableApplicationContext
|
||||
import org.springframework.core.io.ClassPathResource
|
||||
import org.testcontainers.containers.PostgreSQLContainer
|
||||
|
||||
@Suppress("unused")
|
||||
class PostgresInitializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
|
||||
|
||||
override fun initialize(applicationContext: ConfigurableApplicationContext) {
|
||||
postgres().apply {
|
||||
TestPropertyValues.of(
|
||||
"spring.r2dbc.url=r2dbc:pool:postgresql://$host:$firstMappedPort/$databaseName",
|
||||
"spring.r2dbc.username=$username",
|
||||
"spring.r2dbc.password=$password",
|
||||
).applyTo(applicationContext)
|
||||
}
|
||||
}
|
||||
|
||||
private fun postgres(): PostgreSQLContainer<*> = PostgreSQLContainer("postgres:17")
|
||||
.withReuse(true)
|
||||
.apply {
|
||||
"postgres/schema.sql".let {
|
||||
if (ClassPathResource(it).exists()) {
|
||||
withInitScript(it)
|
||||
}
|
||||
}
|
||||
start()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user