diff --git a/build.gradle.kts b/build.gradle.kts index c546bbb..216e7fb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -41,8 +41,7 @@ val mockkVersion = "1.13.4" val springMockkVersion = "4.0.2" val testcontainersVersion = "1.19.3" val kotestVersion = "5.7.2" -val kotestExtensionTestcontainers = "2.0.2" -val kotestExtensionSpring = "1.1.3" +val kotestExtensionSpringVersion = "1.1.3" dependencies { // Spring @@ -90,13 +89,12 @@ dependencies { testImplementation("com.ninja-squad:springmockk:$springMockkVersion") // Testcontainers - testImplementation("org.testcontainers:testcontainers:$testcontainersVersion") + testImplementation("org.testcontainers:testcontainers") // Kotest testImplementation("io.kotest:kotest-runner-junit5:$kotestVersion") testImplementation("io.kotest:kotest-assertions-core:$kotestVersion") - testImplementation("io.kotest.extensions:kotest-extensions-testcontainers:$kotestExtensionTestcontainers") - testImplementation("io.kotest.extensions:kotest-extensions-spring:$kotestExtensionSpring") + testImplementation("io.kotest.extensions:kotest-extensions-spring:$kotestExtensionSpringVersion") // Mock Web Server testImplementation("com.squareup.okhttp3:mockwebserver") diff --git a/src/test/kotlin/kr/galaxyhub/sc/config/EnableTestcontianers.kt b/src/test/kotlin/kr/galaxyhub/sc/config/EnableTestcontianers.kt new file mode 100644 index 0000000..6849318 --- /dev/null +++ b/src/test/kotlin/kr/galaxyhub/sc/config/EnableTestcontianers.kt @@ -0,0 +1,5 @@ +package kr.galaxyhub.sc.config + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.RUNTIME) +annotation class EnableTestcontianers diff --git a/src/test/kotlin/kr/galaxyhub/sc/config/KotestProjectConfig.kt b/src/test/kotlin/kr/galaxyhub/sc/config/KotestProjectConfig.kt deleted file mode 100644 index 7bc0007..0000000 --- a/src/test/kotlin/kr/galaxyhub/sc/config/KotestProjectConfig.kt +++ /dev/null @@ -1,9 +0,0 @@ -package kr.galaxyhub.sc.config - -import io.kotest.core.config.AbstractProjectConfig -import io.kotest.extensions.spring.SpringExtension - -class KotestProjectConfig : AbstractProjectConfig() { - - override fun extensions() = listOf(SpringExtension) -} diff --git a/src/test/kotlin/kr/galaxyhub/sc/config/TestContainerExtension.kt b/src/test/kotlin/kr/galaxyhub/sc/config/TestContainerExtension.kt new file mode 100644 index 0000000..8676f5d --- /dev/null +++ b/src/test/kotlin/kr/galaxyhub/sc/config/TestContainerExtension.kt @@ -0,0 +1,43 @@ +package kr.galaxyhub.sc.config + +import io.kotest.core.extensions.ProjectExtension +import io.kotest.core.project.ProjectContext +import io.kotest.core.spec.AutoScan +import io.kotest.mpp.hasAnnotation +import java.io.File +import kotlin.reflect.full.superclasses +import org.slf4j.LoggerFactory +import org.testcontainers.containers.DockerComposeContainer +import org.testcontainers.containers.output.Slf4jLogConsumer +import org.testcontainers.containers.wait.strategy.ShellStrategy + +@AutoScan +class TestContainerExtension : ProjectExtension { + + private val containers = mutableListOf>() + + override suspend fun interceptProject(context: ProjectContext, callback: suspend (ProjectContext) -> Unit) { + if (isTestcontianersEnable(context)) { + DockerComposeContainer(File("src/test/resources/docker-compose.yml")).apply { + waitingFor( + "test_mysql", + ShellStrategy().withCommand("mysql -u'test' -p'1234' -e'select 1' && sleep 2") + ) + withLogConsumer("test_mysql", Slf4jLogConsumer(LoggerFactory.getLogger(javaClass))) + start() + }.also { + containers.add(it) + } + } + callback(context) + containers.forEach { it.stop() } + } + + private fun isTestcontianersEnable(context: ProjectContext): Boolean { + val hasAnnotationItself = context.suite.specs.stream() + .anyMatch { it.kclass.hasAnnotation() } + return if (hasAnnotationItself) true else context.suite.specs.stream() + .flatMap { it.kclass.superclasses.stream() } + .anyMatch { it.hasAnnotation() } + } +} diff --git a/src/test/kotlin/kr/galaxyhub/sc/config/spec/ControllerTestSpec.kt b/src/test/kotlin/kr/galaxyhub/sc/config/spec/ControllerTestSpec.kt index ac93ca4..3e815b5 100644 --- a/src/test/kotlin/kr/galaxyhub/sc/config/spec/ControllerTestSpec.kt +++ b/src/test/kotlin/kr/galaxyhub/sc/config/spec/ControllerTestSpec.kt @@ -3,6 +3,7 @@ package kr.galaxyhub.sc.config.spec import io.kotest.core.spec.style.DescribeSpec import io.kotest.core.test.TestCase import io.kotest.core.test.TestResult +import io.kotest.extensions.spring.SpringExtension import io.mockk.clearAllMocks import io.mockk.mockkClass import org.junit.platform.commons.util.ClassFilter @@ -19,6 +20,8 @@ import org.springframework.stereotype.Service @AutoConfigureRestDocs abstract class ControllerTestSpec(body: DescribeSpec.() -> Unit = {}) : DescribeSpec(body) { + override fun extensions() = listOf(SpringExtension) + override suspend fun afterEach(testCase: TestCase, result: TestResult) { clearAllMocks() } diff --git a/src/test/kotlin/kr/galaxyhub/sc/config/spec/IntegrationSpec.kt b/src/test/kotlin/kr/galaxyhub/sc/config/spec/IntegrationSpec.kt index 7d67a27..9d34c33 100644 --- a/src/test/kotlin/kr/galaxyhub/sc/config/spec/IntegrationSpec.kt +++ b/src/test/kotlin/kr/galaxyhub/sc/config/spec/IntegrationSpec.kt @@ -1,27 +1,13 @@ package kr.galaxyhub.sc.config.spec -import io.kotest.core.extensions.install import io.kotest.core.spec.style.DescribeSpec -import io.kotest.extensions.testcontainers.ContainerLifecycleMode -import io.kotest.extensions.testcontainers.DockerComposeContainerExtension -import java.io.File -import org.slf4j.LoggerFactory +import io.kotest.extensions.spring.SpringExtension +import kr.galaxyhub.sc.config.EnableTestcontianers import org.springframework.boot.test.context.SpringBootTest -import org.testcontainers.containers.output.Slf4jLogConsumer -import org.testcontainers.containers.wait.strategy.ShellStrategy @SpringBootTest +@EnableTestcontianers abstract class IntegrationSpec(body: DescribeSpec.() -> Unit = {}) : DescribeSpec(body) { - private val log = LoggerFactory.getLogger(javaClass) - - init { - install(DockerComposeContainerExtension(File("src/test/resources/docker-compose.yml"), ContainerLifecycleMode.Project)) - .apply { - waitingFor("test_mysql", ShellStrategy().withCommand("mysql -u'test' -p'1234' -e'select 1' && sleep 2")) - withLogConsumer("test_mysql", Slf4jLogConsumer(log)) - }.apply { - start() - } - } + override fun extensions() = listOf(SpringExtension) } diff --git a/src/test/resources/docker-compose.yml b/src/test/resources/docker-compose.yml index e1b69a9..07b8c8d 100644 --- a/src/test/resources/docker-compose.yml +++ b/src/test/resources/docker-compose.yml @@ -1,6 +1,4 @@ -version: "3.3" -volumes: - mysql_data: { } +version: "3" services: test_mysql: image: mysql:8.0.33 @@ -8,14 +6,10 @@ services: - "13306:3306" environment: TZ: Asia/Seoul + MYSQL_DATABASE: test + MYSQL_ROOT_PASSWORD: 1234 MYSQL_USER: test MYSQL_PASSWORD: 1234 - MYSQL_ROOT_PASSWORD: 1234 - MYSQL_DATABASE: test - volumes: - - mysql_data:/var/lib/mysql/ - - ./sql:/docker-entrypoint-initdb.d command: - - "--character-set-server=utf8mb4" - - "--collation-server=utf8mb4_unicode_ci" - - "--skip-character-set-client-handshake" + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci