Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Jooq 테스트와 TestContainer 설정을 추가합니다 #33

Merged
merged 24 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
65116f0
remove: application-data-*.yml 삭제
belljun3395 Jun 8, 2024
4d3ab91
remove: Data 모듈 의존성 삭제
belljun3395 Jun 8, 2024
84df781
move: *.sql 위치 변경
belljun3395 Jun 8, 2024
1386f93
feat: api-repo 모듈 추가
belljun3395 Jun 8, 2024
d732db7
feat: api-repo 모듈 jdbc, flyway 의존성 추가
belljun3395 Jun 8, 2024
a23270a
feat: data 모듈의 DataMigration 복사 및 실행 태스크 추가
belljun3395 Jun 8, 2024
918892f
feat: api-repo 모듈 구성 설정 추가
belljun3395 Jun 8, 2024
890688f
feat: DataSourceConfig 추가
belljun3395 Jun 8, 2024
c1b7606
feat: FlywayConfig 추가
belljun3395 Jun 8, 2024
049798c
feat: JOOQ 버전 추가
belljun3395 Jun 8, 2024
5194a99
feat: api-repo 모듈 jooq 의존성 추가
belljun3395 Jun 8, 2024
0a89b36
feat: api-repo 모듈 jooqCodegen 테스크 정의 및 사전 조건 추가
belljun3395 Jun 8, 2024
20c2ccc
refactor: 초기 테이블 스키마와 일치하도록 수정
belljun3395 Jun 9, 2024
1b7abb1
feat: testcontainers 의존성 추가
belljun3395 Jun 10, 2024
cc81d43
feat: testcontainers를 위한 docker-compose 추가
belljun3395 Jun 10, 2024
48b5205
feat: RepoTestContainerInitializer 구현
belljun3395 Jun 10, 2024
639db89
feat: JooqTestConfig 추가
belljun3395 Jun 9, 2024
3ff3e60
feat: JooqTestSpec 추가
belljun3395 Jun 9, 2024
4ee56d9
feat: RepoTestContainerInitializer 적용
belljun3395 Jun 10, 2024
0a9c27d
feat: application-test 구성 추가
belljun3395 Jun 9, 2024
f930318
test: Jooq 사용 예시를 위한 _SampleJooqTest 구현
belljun3395 Jun 9, 2024
aa3a153
refactor: 변경된 스키마에 맞추어 테스트 수정
belljun3395 Jun 13, 2024
cd69db1
Merge branch 'main' into feat/#32_belljun3395
belljun3395 Jun 13, 2024
ecd9d27
Merge branch 'main' into feat/#32_belljun3395
belljun3395 Jun 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions api-repo/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
tasks.getByName("bootJar") {
enabled = false
}

tasks.getByName("jar") {
enabled = true
}

plugins {
/** jooq */
id("org.jooq.jooq-codegen-gradle") version DependencyVersion.JOOQ
}

sourceSets {
main {
java {
val mainDir = "src/main/kotlin"
val jooqDir = "src/generated"
srcDirs(mainDir, jooqDir)
}
}
}

dependencies {
/** spring starter */
implementation("org.springframework.boot:spring-boot-starter-data-jdbc")
implementation("com.mysql:mysql-connector-j")

/** flyway */
implementation("org.flywaydb:flyway-core:${DependencyVersion.FLYWAY}")
implementation("org.flywaydb:flyway-mysql")

/** jooq */
implementation("org.springframework.boot:spring-boot-starter-jooq")
implementation("org.jooq:jooq:${DependencyVersion.JOOQ}")
implementation("org.jooq:jooq-meta:${DependencyVersion.JOOQ}")
implementation("org.jooq:jooq-codegen:${DependencyVersion.JOOQ}")
jooqCodegen("org.jooq:jooq-meta-extensions:${DependencyVersion.JOOQ}")

/** test container */
implementation(platform("org.testcontainers:testcontainers-bom:${DependencyVersion.TEST_CONTAINER}"))
testImplementation("org.testcontainers:mysql")
}

/** copy data migration */
tasks.create("copyDataMigration") {
doLast {
val root = rootDir
val flyWayResourceDir = "/db/migration/entity"
val dataMigrationDir = "$root/data/$flyWayResourceDir"
File(dataMigrationDir).walkTopDown().forEach {
if (it.isFile) {
it.copyTo(
File("${project.projectDir}/src/main/resources$flyWayResourceDir/${it.name}"),
true
)
}
}
}
}

/** copy data migration before compile kotlin */
tasks.getByName("compileKotlin") {
dependsOn("copyDataMigration")
}

/** jooq codegen after copy data migration */
tasks.getByName("jooqCodegen") {
dependsOn("copyDataMigration")
}

jooq {
configuration {
generator {
database {
name = "org.jooq.meta.extensions.ddl.DDLDatabase"
properties {
// Specify the location of your SQL script.
// You may use ant-style file matching, e.g. /path/**/to/*.sql
//
// Where:
// - ** matches any directory subtree
// - * matches any number of characters in a directory / file name
// - ? matches a single character in a directory / file name
property {
key = "scripts"
value = "src/main/resources/db/migration/**/*.sql"
}

// The sort order of the scripts within a directory, where:
//
// - semantic: sorts versions, e.g. v-3.10.0 is after v-3.9.0 (default)
// - alphanumeric: sorts strings, e.g. v-3.10.0 is before v-3.9.0
// - flyway: sorts files the same way as flyway does
// - none: doesn't sort directory contents after fetching them from the directory
property {
key = "sort"
value = "flyway"
}

// The default schema for unqualified objects:
//
// - public: all unqualified objects are located in the PUBLIC (upper case) schema
// - none: all unqualified objects are located in the default schema (default)
//
// This configuration can be overridden with the schema mapping feature
property {
key = "unqualifiedSchema"
value = "none"
}

// The default name case for unquoted objects:
//
// - as_is: unquoted object names are kept unquoted
// - upper: unquoted object names are turned into upper case (most databases)
// - lower: unquoted object names are turned into lower case (e.g. PostgreSQL)
property {
key = "defaultNameCase"
value = "as_is"
}
}
}

generate {
isDeprecated = false
isRecords = true
isImmutablePojos = true
isFluentSetters = true
isJavaTimeTypes = true
}

target {
packageName = "jooq.jooq_dsl"
directory = "src/generated"
encoding = "UTF-8"
}
}
}
}
16 changes: 16 additions & 0 deletions api-repo/src/main/kotlin/com/few/api/repo/config/ApiRepoConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.few.api.repo.config

import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration

@Configuration
@ComponentScan(basePackages = [ApiRepoConfig.BASE_PACKAGE])
class ApiRepoConfig {
companion object {
const val BASE_PACKAGE = "com.few.api.repo"
const val SERVICE_NAME = "few"
const val MODULE_NAME = "few-api-repo"
const val BEAN_NAME_PREFIX = "fewApiRepo"
const val PROPERTY_PREFIX = SERVICE_NAME + "." + MODULE_NAME
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.few.api.repo.datasource

import com.few.api.repo.config.ApiRepoConfig
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.boot.jdbc.DataSourceBuilder
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.jdbc.datasource.DataSourceTransactionManager
import org.springframework.transaction.PlatformTransactionManager
import javax.sql.DataSource

@Configuration
class DataSourceConfig {

companion object {
const val API_DATASOURCE = ApiRepoConfig.BEAN_NAME_PREFIX + "DataSource"
const val API_TX = ApiRepoConfig.BEAN_NAME_PREFIX + "TransactionManager"
}

@Bean(name = [API_DATASOURCE])
@ConfigurationProperties(prefix = "spring.datasource")
fun apiDataSource(): DataSource {
return DataSourceBuilder.create().build()
}

@Bean(name = [API_TX])
fun apiTransactionManager(): PlatformTransactionManager {
return DataSourceTransactionManager(apiDataSource())
}
}
Original file line number Diff line number Diff line change
@@ -1,50 +1,54 @@
package com.few.data.flyway
package com.few.api.repo.flyway

import com.few.data.config.DataConfig
import com.few.api.repo.config.ApiRepoConfig
import com.few.api.repo.datasource.DataSourceConfig
import org.flywaydb.core.Flyway
import org.flywaydb.core.api.configuration.FluentConfiguration
import org.springframework.beans.factory.annotation.Qualifier
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationInitializer
import org.springframework.boot.autoconfigure.flyway.FlywayProperties
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.context.annotation.Profile
import java.util.function.Consumer
import javax.sql.DataSource

@Configuration
@Import(DataSourceConfig::class)
class FlywayConfig {
@Bean(name = [DataConfig.BEAN_NAME_PREFIX + "Flyway"])
@Bean(name = [ApiRepoConfig.BEAN_NAME_PREFIX + "Flyway"])
fun flyway(
configuration: org.flywaydb.core.api.configuration.Configuration?
): Flyway {
return Flyway(configuration)
}

@Profile("!new")
@Bean(name = [DataConfig.BEAN_NAME_PREFIX + "FlywayValidateInitializer"])
@Bean(name = [ApiRepoConfig.BEAN_NAME_PREFIX + "FlywayValidateInitializer"])
fun flywayValidateInitializer(
flyway: Flyway?
): FlywayMigrationInitializer {
return FlywayMigrationInitializer(flyway) { obj: Flyway -> obj.validate() }
}

@Bean(name = [DataConfig.BEAN_NAME_PREFIX + "FlywayMigrationInitializer"])
@Bean(name = [ApiRepoConfig.BEAN_NAME_PREFIX + "FlywayMigrationInitializer"])
fun flywayMigrationInitializer(
flyway: Flyway?
): FlywayMigrationInitializer {
return FlywayMigrationInitializer(flyway) { obj: Flyway -> obj.migrate() }
}

@Bean(name = [DataConfig.BEAN_NAME_PREFIX + "FlywayProperties"])
@Bean(name = [ApiRepoConfig.BEAN_NAME_PREFIX + "FlywayProperties"])
@ConfigurationProperties(prefix = "spring.flyway")
fun flywayProperties(): FlywayProperties {
return FlywayProperties()
}

@Bean(name = [DataConfig.BEAN_NAME_PREFIX + "FlywayConfiguration"])
@Bean(name = [ApiRepoConfig.BEAN_NAME_PREFIX + "FlywayConfiguration"])
fun configuration(
dataSource: DataSource?
@Qualifier(DataSourceConfig.API_DATASOURCE) dataSource: DataSource?
): org.flywaydb.core.api.configuration.Configuration {
val configuration = FluentConfiguration()
configuration.dataSource(dataSource)
Expand Down
11 changes: 11 additions & 0 deletions api-repo/src/main/resources/application-api-repo-local.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
spring:
datasource:
jdbcUrl: jdbc:mysql://localhost:13306/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
flyway:
locations: classpath:db/migration/entity
sql-migration-suffixes: sql
baseline-on-migrate: true
baseline-version: 0
11 changes: 11 additions & 0 deletions api-repo/src/main/resources/application-api-repo-prd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
spring:
datasource:
jdbcUrl: ${DB_HOSTNAME}/api?allowPublicKeyRetrieval=true&rewriteBatchedStatements=true
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver
flyway:
locations: classpath:db/migration/entity
sql-migration-suffixes: sql
baseline-on-migrate: true
baseline-version: 0
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.few.api.repo

import org.springframework.context.ApplicationContextInitializer
import org.springframework.context.ConfigurableApplicationContext
import org.testcontainers.containers.DockerComposeContainer
import java.io.File

class RepoTestContainerInitializer : ApplicationContextInitializer<ConfigurableApplicationContext> {
private val log: org.slf4j.Logger =
org.slf4j.LoggerFactory.getLogger(RepoTestContainerInitializer::class.java)

companion object {
private const val MYSQL = "mysql"
private const val MYSQL_PORT = 3306

private val dockerCompose =
DockerComposeContainer(File("src/test/resources/docker-compose.yml"))
.withExposedService(MYSQL, MYSQL_PORT)
}

override fun initialize(applicationContext: ConfigurableApplicationContext) {
log.debug("===== set up test containers =====")

dockerCompose.start()

log.debug("===== success set up test containers =====")
}
}
11 changes: 11 additions & 0 deletions api-repo/src/test/kotlin/com/few/api/repo/jooq/JooqTestConfig.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.few.api.repo.jooq

import com.few.api.repo.config.ApiRepoConfig
import org.springframework.boot.autoconfigure.EnableAutoConfiguration
import org.springframework.boot.test.context.TestConfiguration
import org.springframework.context.annotation.ComponentScan

@TestConfiguration
@EnableAutoConfiguration
@ComponentScan(basePackages = [ApiRepoConfig.BASE_PACKAGE])
class JooqTestConfig
12 changes: 12 additions & 0 deletions api-repo/src/test/kotlin/com/few/api/repo/jooq/JooqTestSpec.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.few.api.repo.jooq

import com.few.api.repo.RepoTestContainerInitializer
import com.few.api.repo.config.ApiRepoConfig
import org.springframework.boot.test.context.SpringBootTest
import org.springframework.test.context.ActiveProfiles
import org.springframework.test.context.ContextConfiguration

@ActiveProfiles("new", "test", "api-repo-local")
@SpringBootTest(classes = [ApiRepoConfig::class])
@ContextConfiguration(initializers = [RepoTestContainerInitializer::class])
abstract class JooqTestSpec
Loading
Loading