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:
13
README.md
13
README.md
@@ -2,6 +2,19 @@
|
|||||||
|
|
||||||
In the forge of software development, where annotations ignite, A crucible of testing, common classes to excite. Each annotation examined, with attention to detail and might, Their effects on code behavior, tested through day and night. From mockk objects to test doubles, a toolkit to refine, Developers and testers, their skills to redefine. The Annotation Validator, a sentinel of code integrity true, A library of verification, where testing wisdom shines anew.
|
In the forge of software development, where annotations ignite, A crucible of testing, common classes to excite. Each annotation examined, with attention to detail and might, Their effects on code behavior, tested through day and night. From mockk objects to test doubles, a toolkit to refine, Developers and testers, their skills to redefine. The Annotation Validator, a sentinel of code integrity true, A library of verification, where testing wisdom shines anew.
|
||||||
|
|
||||||
|
## Postgres Test Container
|
||||||
|
|
||||||
|
`@PostgresContainer` Annotation for integration tests.
|
||||||
|
|
||||||
|
Initialize Postgres test container using spring properties for R2DBC,
|
||||||
|
script located in `src/<test path>/resources/postgres` folder.
|
||||||
|
|
||||||
|
* `schema.sql` file containing all structure and functions when star.
|
||||||
|
* `data.sql` file containing all data added before all test.
|
||||||
|
* `reset.sql` file containing all to reset database after all test.
|
||||||
|
|
||||||
|
if file exist it will be loaded...
|
||||||
|
|
||||||
## Releasing library
|
## Releasing library
|
||||||
|
|
||||||
Run `release.sh` script from `master` branch.
|
Run `release.sh` script from `master` branch.
|
||||||
|
|||||||
@@ -7,7 +7,11 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation(hlaeja.kotlinx.coroutines)
|
||||||
|
implementation(hlaeja.springboot.starter.r2dbc)
|
||||||
implementation(hlaeja.springboot.starter.test)
|
implementation(hlaeja.springboot.starter.test)
|
||||||
|
implementation(hlaeja.testcontainers.junit)
|
||||||
|
implementation(hlaeja.testcontainers.postgresql)
|
||||||
|
|
||||||
testRuntimeOnly(hlaeja.junit.platform.launcher)
|
testRuntimeOnly(hlaeja.junit.platform.launcher)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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