From 84ae719247cb4bb2d6a550e520394fa9113ebd31 Mon Sep 17 00:00:00 2001 From: can019 Date: Sun, 7 Sep 2025 13:19:53 +0900 Subject: [PATCH 1/6] chore: e2e test config --- apps/user-service/build.gradle | 1 + .../main/resources/application-test-e2e.yml | 13 ++ .../src/main/resources/log4j2-production.yml | 126 ++++++++++++++++++ .../icebang/E2eTestConfiguration.java | 38 ++++++ 4 files changed, 178 insertions(+) create mode 100644 apps/user-service/src/main/resources/application-test-e2e.yml create mode 100644 apps/user-service/src/main/resources/log4j2-production.yml create mode 100644 apps/user-service/src/test/java/com/gltkorea/icebang/E2eTestConfiguration.java diff --git a/apps/user-service/build.gradle b/apps/user-service/build.gradle index 64a70975..a4d0f046 100644 --- a/apps/user-service/build.gradle +++ b/apps/user-service/build.gradle @@ -65,6 +65,7 @@ dependencies { testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.5' testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.testcontainers:junit-jupiter' + testImplementation 'org.testcontainers:mariadb' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } diff --git a/apps/user-service/src/main/resources/application-test-e2e.yml b/apps/user-service/src/main/resources/application-test-e2e.yml new file mode 100644 index 00000000..e41568fb --- /dev/null +++ b/apps/user-service/src/main/resources/application-test-e2e.yml @@ -0,0 +1,13 @@ +spring: + config: + activate: + on-profile: test-e2e + +mybatis: + mapper-locations: classpath:mybatis/mapper/**/*.xml + type-aliases-package: com.gltkorea.icebang.dto + configuration: + map-underscore-to-camel-case: true + +logging: + config: classpath:log4j2-production.yml \ No newline at end of file diff --git a/apps/user-service/src/main/resources/log4j2-production.yml b/apps/user-service/src/main/resources/log4j2-production.yml new file mode 100644 index 00000000..d1afc02b --- /dev/null +++ b/apps/user-service/src/main/resources/log4j2-production.yml @@ -0,0 +1,126 @@ +Configuration: + name: develop + + properties: + property: + - name: "log-path" + value: "./logs" + - name: "charset-UTF-8" + value: "UTF-8" + # 통일된 콘솔 패턴 - 모든 로그에 RequestId 포함 + - name: "console-layout-pattern" + value: "%highlight{[%-5level]} [%X{traceId}] %d{MM-dd HH:mm:ss} [%t] %n %msg%n%n" + # 파일용 상세 패턴 - RequestId 포함 + - name: "file-layout-pattern" + value: "[%X{traceId}] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" + # 로그 파일 경로들 + - name: "info-log" + value: ${log-path}/user-service/info.log + - name: "error-log" + value: ${log-path}/user-service/error.log + - name: "auth-log" + value: ${log-path}/user-service/auth.log + - name: "json-log" + value: ${log-path}/user-service/json-info.log + + # [Appenders] 로그 기록방식 정의 + Appenders: + # 통일된 콘솔 출력 + Console: + name: console-appender + target: SYSTEM_OUT + PatternLayout: + pattern: ${console-layout-pattern} + + # 롤링 파일 로그 + RollingFile: + name: rolling-file-appender + fileName: ${log-path}/rolling-file.log + filePattern: "logs/archive/rolling-file.log.%d{yyyy-MM-dd-hh-mm}_%i.gz" + PatternLayout: + charset: ${charset-UTF-8} + pattern: ${file-layout-pattern} + Policies: + SizeBasedTriggeringPolicy: + size: "200KB" + TimeBasedTriggeringPolicy: + interval: "1" + DefaultRollOverStrategy: + max: "30" + fileIndex: "max" + + # 파일 로그들 + File: + - name: file-info-appender + fileName: ${info-log} + PatternLayout: + pattern: ${file-layout-pattern} + - name: file-error-appender + fileName: ${error-log} + PatternLayout: + pattern: ${file-layout-pattern} + - name: file-auth-appender + fileName: ${auth-log} + PatternLayout: + pattern: ${file-layout-pattern} + - name: file-json-info-appender + fileName: ${json-log} + PatternLayout: + pattern: ${file-layout-pattern} + + # [Loggers] 로그 출력 범위를 정의 + Loggers: + # [Loggers - Root] 모든 로그를 기록하는 최상위 로그를 정의 + Root: + level: OFF + AppenderRef: + - ref: console-appender + - ref: rolling-file-appender + + # [Loggers - Loggers] 특정 패키지나 클래스에 대한 로그를 정의 + Logger: + # 1. Spring Framework 로그 + - name: org.springframework + additivity: "false" + level: DEBUG + AppenderRef: + - ref: console-appender + - ref: file-info-appender + - ref: file-error-appender + + # 2. 애플리케이션 로그 + - name: com.gltkorea.icebang + additivity: "false" + level: TRACE + AppenderRef: + - ref: console-appender + - ref: file-info-appender + - ref: file-error-appender + + # 3. HikariCP 로그 비활성화 + - name: com.zaxxer.hikari + level: OFF + + # 4. Spring Security 로그 - 인증/인가 추적에 중요 + - name: org.springframework.security + level: DEBUG + additivity: "false" + AppenderRef: + - ref: console-appender + - ref: file-auth-appender + + # 5. 웹 요청 로그 - 요청 처리 과정 추적 + - name: org.springframework.web + level: DEBUG + additivity: "false" + AppenderRef: + - ref: console-appender + - ref: file-info-appender + + # 6. 트랜잭션 로그 - DB 작업 추적 + - name: org.springframework.transaction + level: DEBUG + additivity: "false" + AppenderRef: + - ref: console-appender + - ref: file-info-appender \ No newline at end of file diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/E2eTestConfiguration.java b/apps/user-service/src/test/java/com/gltkorea/icebang/E2eTestConfiguration.java new file mode 100644 index 00000000..0898e5c6 --- /dev/null +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/E2eTestConfiguration.java @@ -0,0 +1,38 @@ +package com.gltkorea.icebang; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Bean; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MariaDBContainer; + +@TestConfiguration(proxyBeanMethods = false) +public class E2eTestConfiguration { + + @Bean + @ServiceConnection + MariaDBContainer mariadbContainer() { + return new MariaDBContainer<>("mariadb:11.4") + .withDatabaseName("pre_process") + .withUsername("mariadb") + .withPassword("qwer1234"); + } + + @DynamicPropertySource + static void configureProperties(DynamicPropertyRegistry registry, MariaDBContainer mariadb) { + // MariaDB 연결 설정 + registry.add("spring.datasource.url", mariadb::getJdbcUrl); + registry.add("spring.datasource.username", mariadb::getUsername); + registry.add("spring.datasource.password", mariadb::getPassword); + registry.add("spring.datasource.driver-class-name", () -> "org.mariadb.jdbc.Driver"); + + // HikariCP 설정 + registry.add("spring.hikari.connection-timeout", () -> "30000"); + registry.add("spring.hikari.idle-timeout", () -> "600000"); + registry.add("spring.hikari.max-lifetime", () -> "1800000"); + registry.add("spring.hikari.maximum-pool-size", () -> "10"); + registry.add("spring.hikari.minimum-idle", () -> "5"); + registry.add("spring.hikari.pool-name", () -> "HikariCP-E2E"); + } +} From 425fbccae585a602bc666326a98785d465f497bf Mon Sep 17 00:00:00 2001 From: can019 Date: Sun, 7 Sep 2025 13:21:24 +0900 Subject: [PATCH 2/6] =?UTF-8?q?chore:=20e2e=20test=20configuration=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Changes to be committed: renamed: src/test/java/com/gltkorea/icebang/E2eTestConfiguration.java -> src/test/java/com/gltkorea/icebang/config/E2eTestConfiguration.java --- .../com/gltkorea/icebang/{ => config}/E2eTestConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename apps/user-service/src/test/java/com/gltkorea/icebang/{ => config}/E2eTestConfiguration.java (97%) diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/E2eTestConfiguration.java b/apps/user-service/src/test/java/com/gltkorea/icebang/config/E2eTestConfiguration.java similarity index 97% rename from apps/user-service/src/test/java/com/gltkorea/icebang/E2eTestConfiguration.java rename to apps/user-service/src/test/java/com/gltkorea/icebang/config/E2eTestConfiguration.java index 0898e5c6..054360b1 100644 --- a/apps/user-service/src/test/java/com/gltkorea/icebang/E2eTestConfiguration.java +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/config/E2eTestConfiguration.java @@ -1,4 +1,4 @@ -package com.gltkorea.icebang; +package com.gltkorea.icebang.config; import org.springframework.boot.test.context.TestConfiguration; import org.springframework.boot.testcontainers.service.connection.ServiceConnection; From f7e1b11e2639447e5bdee87e513dfed2e1be7f7c Mon Sep 17 00:00:00 2001 From: can019 Date: Sun, 7 Sep 2025 13:25:43 +0900 Subject: [PATCH 3/6] =?UTF-8?q?chore:=20unit,=20e2e=20test=20profile=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/user-service/build.gradle | 21 +++++++++++++++++++ .../gltkorea/icebang/annotation/E2eTest.java | 10 +++++++++ .../gltkorea/icebang/annotation/UnitTest.java | 10 +++++++++ 3 files changed, 41 insertions(+) create mode 100644 apps/user-service/src/test/java/com/gltkorea/icebang/annotation/E2eTest.java create mode 100644 apps/user-service/src/test/java/com/gltkorea/icebang/annotation/UnitTest.java diff --git a/apps/user-service/build.gradle b/apps/user-service/build.gradle index a4d0f046..e2e8f3f5 100644 --- a/apps/user-service/build.gradle +++ b/apps/user-service/build.gradle @@ -70,6 +70,27 @@ dependencies { } tasks.named('test') { + useJUnitPlatform { + // 기본적으로는 e2e 태그 제외하고 실행 + excludeTags 'e2e' + } + systemProperty 'spring.profiles.active', 'test-unit' +} + +// E2E 테스트 전용 task 추가 +tasks.register('e2eTest', Test) { + useJUnitPlatform { + includeTags 'e2e' + } + + systemProperty 'spring.profiles.active', 'test-e2e' + + // E2E 테스트는 더 긴 시간 허용 + timeout = Duration.ofMinutes(10) +} + +// 모든 테스트 실행 task +tasks.register('allTests', Test) { useJUnitPlatform() } diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/annotation/E2eTest.java b/apps/user-service/src/test/java/com/gltkorea/icebang/annotation/E2eTest.java new file mode 100644 index 00000000..7af9cf40 --- /dev/null +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/annotation/E2eTest.java @@ -0,0 +1,10 @@ +package com.gltkorea.icebang.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface E2eTest {} diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/annotation/UnitTest.java b/apps/user-service/src/test/java/com/gltkorea/icebang/annotation/UnitTest.java new file mode 100644 index 00000000..bace7ed4 --- /dev/null +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/annotation/UnitTest.java @@ -0,0 +1,10 @@ +package com.gltkorea.icebang.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface UnitTest {} From 9c7a9cd155d30abf618535b8259ffbb53ad595ca Mon Sep 17 00:00:00 2001 From: can019 Date: Sun, 7 Sep 2025 13:27:56 +0900 Subject: [PATCH 4/6] feat: Unit, e2e test support class --- .../icebang/support/E2eTestSupport.java | 30 +++++++++++++++++++ .../icebang/support/UnitTestSupport.java | 16 ++++++++++ 2 files changed, 46 insertions(+) create mode 100644 apps/user-service/src/test/java/com/gltkorea/icebang/support/E2eTestSupport.java create mode 100644 apps/user-service/src/test/java/com/gltkorea/icebang/support/UnitTestSupport.java diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/support/E2eTestSupport.java b/apps/user-service/src/test/java/com/gltkorea/icebang/support/E2eTestSupport.java new file mode 100644 index 00000000..d3492a70 --- /dev/null +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/support/E2eTestSupport.java @@ -0,0 +1,30 @@ +package com.gltkorea.icebang.support; + +import org.junit.jupiter.api.Tag; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; + +import com.gltkorea.icebang.config.E2eTestConfiguration; + +@Tag("e2e") +@Import(E2eTestConfiguration.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles("test-e2e") +public abstract class E2eTestSupport { + + @LocalServerPort protected int port; + + @Autowired protected TestRestTemplate restTemplate; + + protected String getBaseUrl() { + return "http://localhost:" + port; + } + + protected String getApiUrl(String path) { + return getBaseUrl() + "/api" + path; + } +} diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/support/UnitTestSupport.java b/apps/user-service/src/test/java/com/gltkorea/icebang/support/UnitTestSupport.java new file mode 100644 index 00000000..07414d89 --- /dev/null +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/support/UnitTestSupport.java @@ -0,0 +1,16 @@ +package com.gltkorea.icebang.support; + +import org.junit.jupiter.api.Tag; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +@Tag("unit") +@SpringBootTest +@ActiveProfiles("test-unit") +public abstract class UnitTestSupport { + + // 공통 유틸리티 메서드들 + protected void assertCommonValidation() { + // 공통 검증 로직 + } +} From d02702ed64d944945ba7e381271f78c853236ebf Mon Sep 17 00:00:00 2001 From: can019 Date: Sun, 7 Sep 2025 13:48:17 +0900 Subject: [PATCH 5/6] test: Test support set up --- .../main/resources/application-test-unit.yml | 39 +++++++++++++++++++ .../src/main/resources/application-test.yml | 34 ---------------- .../{log4j2-test.yml => log4j2-test-unit.yml} | 0 3 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 apps/user-service/src/main/resources/application-test-unit.yml delete mode 100644 apps/user-service/src/main/resources/application-test.yml rename apps/user-service/src/main/resources/{log4j2-test.yml => log4j2-test-unit.yml} (100%) diff --git a/apps/user-service/src/main/resources/application-test-unit.yml b/apps/user-service/src/main/resources/application-test-unit.yml new file mode 100644 index 00000000..859ce9f4 --- /dev/null +++ b/apps/user-service/src/main/resources/application-test-unit.yml @@ -0,0 +1,39 @@ +# src/test/resources/application-test.yml +spring: + config: + activate: + on-profile: test-unit + + # H2 인메모리 데이터베이스 설정 (Unit Test용) + datasource: + url: jdbc:h2:mem:testdb;MODE=MariaDB;DB_CLOSE_DELAY=-1 + username: sa + password: + driver-class-name: org.h2.Driver + + # H2 웹 콘솔 활성화 (디버깅용) + h2: + console: + enabled: true + + hikari: + connection-timeout: 30000 + idle-timeout: 600000 + max-lifetime: 1800000 + maximum-pool-size: 10 + minimum-idle: 5 + pool-name: HikariCP-MyBatis + + # JPA 설정 (H2용) + jpa: + hibernate: + ddl-auto: create-drop + show-sql: true + properties: + hibernate: + dialect: org.hibernate.dialect.H2Dialect + + # SQL 스크립트 초기화 설정 + sql: + init: + mode: embedded # H2 같은 \ No newline at end of file diff --git a/apps/user-service/src/main/resources/application-test.yml b/apps/user-service/src/main/resources/application-test.yml deleted file mode 100644 index 63217124..00000000 --- a/apps/user-service/src/main/resources/application-test.yml +++ /dev/null @@ -1,34 +0,0 @@ -# src/test/resources/application-test.yml -spring: - config: - activate: - on-profile: test - - # PostgreSQL 데이터베이스 연결 설정 - datasource: - url: jdbc:postgresql://localhost:5432/pre_process - username: postgres - password: qwer1234 - driver-class-name: org.postgresql.Driver - - hikari: - connection-timeout: 30000 - idle-timeout: 600000 - max-lifetime: 1800000 - maximum-pool-size: 10 - minimum-idle: 5 - pool-name: HikariCP-MyBatis - - # SQL 스크립트 초기화 설정 추가 - sql: - init: - mode: always # 내장 DB가 아니더라도 항상 스크립트를 실행하도록 설정 - -mybatis: - mapper-locations: classpath:mybatis/mapper/**/*.xml - type-aliases-package: com.gltkorea.icebang.dto - configuration: - map-underscore-to-camel-case: true - -logging: - config: classpath:log4j2-test.yml \ No newline at end of file diff --git a/apps/user-service/src/main/resources/log4j2-test.yml b/apps/user-service/src/main/resources/log4j2-test-unit.yml similarity index 100% rename from apps/user-service/src/main/resources/log4j2-test.yml rename to apps/user-service/src/main/resources/log4j2-test-unit.yml From c2c826c5a83d34b33b126d9a233adf101a3c3050 Mon Sep 17 00:00:00 2001 From: can019 Date: Sun, 7 Sep 2025 13:48:44 +0900 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20Test=EA=B0=80=20=EC=A0=9C=EB=8C=80?= =?UTF-8?q?=EB=A1=9C=20=EC=88=98=ED=96=89=EB=90=98=EC=A7=80=20=EC=95=8A?= =?UTF-8?q?=EB=8D=98=20=EB=AC=B8=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit configure fixed (unit, e2e) --- apps/user-service/build.gradle | 1 + .../email/service/MockEmailService.java | 2 +- .../main/resources/application-test-unit.yml | 31 +++++++++----- .../icebang/DatabaseConnectionTest.java | 2 +- .../icebang/controller/TestController.java | 15 +++++++ .../icebang/support/E2eTestSupportTest.java | 31 ++++++++++++++ .../icebang/support/UnitTestSupportTest.java | 41 ++++++++++++++++++ .../resources/sql/create-users-entity.sql | 42 +++++++++++-------- 8 files changed, 135 insertions(+), 30 deletions(-) create mode 100644 apps/user-service/src/test/java/com/gltkorea/icebang/controller/TestController.java create mode 100644 apps/user-service/src/test/java/com/gltkorea/icebang/support/E2eTestSupportTest.java create mode 100644 apps/user-service/src/test/java/com/gltkorea/icebang/support/UnitTestSupportTest.java diff --git a/apps/user-service/build.gradle b/apps/user-service/build.gradle index e2e8f3f5..42063732 100644 --- a/apps/user-service/build.gradle +++ b/apps/user-service/build.gradle @@ -66,6 +66,7 @@ dependencies { testImplementation 'org.springframework.security:spring-security-test' testImplementation 'org.testcontainers:junit-jupiter' testImplementation 'org.testcontainers:mariadb' + testImplementation 'com.h2database:h2' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } diff --git a/apps/user-service/src/main/java/com/gltkorea/icebang/domain/email/service/MockEmailService.java b/apps/user-service/src/main/java/com/gltkorea/icebang/domain/email/service/MockEmailService.java index 029001ec..6ccaffc9 100644 --- a/apps/user-service/src/main/java/com/gltkorea/icebang/domain/email/service/MockEmailService.java +++ b/apps/user-service/src/main/java/com/gltkorea/icebang/domain/email/service/MockEmailService.java @@ -8,7 +8,7 @@ import lombok.extern.slf4j.Slf4j; @Service -@Profile({"unit-test", "local", "develop"}) +@Profile({"test-unit", "test-e2e", "local", "develop"}) @Slf4j public class MockEmailService implements EmailService { diff --git a/apps/user-service/src/main/resources/application-test-unit.yml b/apps/user-service/src/main/resources/application-test-unit.yml index 859ce9f4..df3f9cba 100644 --- a/apps/user-service/src/main/resources/application-test-unit.yml +++ b/apps/user-service/src/main/resources/application-test-unit.yml @@ -1,4 +1,4 @@ -# src/test/resources/application-test.yml +# src/test/resources/application-test-unit.yml spring: config: activate: @@ -6,24 +6,24 @@ spring: # H2 인메모리 데이터베이스 설정 (Unit Test용) datasource: - url: jdbc:h2:mem:testdb;MODE=MariaDB;DB_CLOSE_DELAY=-1 + url: jdbc:h2:mem:testdb;MODE=MariaDB;DB_CLOSE_DELAY=-1;DATABASE_TO_LOWER=TRUE username: sa password: driver-class-name: org.h2.Driver + hikari: + connection-init-sql: "SET MODE MariaDB" + connection-timeout: 30000 + idle-timeout: 600000 + max-lifetime: 1800000 + maximum-pool-size: 10 + minimum-idle: 5 + pool-name: HikariCP-MyBatis # H2 웹 콘솔 활성화 (디버깅용) h2: console: enabled: true - hikari: - connection-timeout: 30000 - idle-timeout: 600000 - max-lifetime: 1800000 - maximum-pool-size: 10 - minimum-idle: 5 - pool-name: HikariCP-MyBatis - # JPA 설정 (H2용) jpa: hibernate: @@ -36,4 +36,13 @@ spring: # SQL 스크립트 초기화 설정 sql: init: - mode: embedded # H2 같은 \ No newline at end of file + mode: embedded + +mybatis: + mapper-locations: classpath:mybatis/mapper/**/*.xml + type-aliases-package: com.gltkorea.icebang.dto + configuration: + map-underscore-to-camel-case: true + +logging: + config: classpath:log4j2-test-unit.yml \ No newline at end of file diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/DatabaseConnectionTest.java b/apps/user-service/src/test/java/com/gltkorea/icebang/DatabaseConnectionTest.java index fbcd5a9e..e744873b 100644 --- a/apps/user-service/src/test/java/com/gltkorea/icebang/DatabaseConnectionTest.java +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/DatabaseConnectionTest.java @@ -25,7 +25,7 @@ // @SpringBootTest // @Import(TestcontainersConfiguration.class) // @AutoConfigureTestDatabase(replace = Replace.NONE) -// @ActiveProfiles("test") // application-test.yml 설정을 활성화 +// @ActiveProfiles("test") // application-test-unit.yml 설정을 활성화 // @Transactional // 테스트 후 데이터 롤백 // @Sql( // scripts = {"classpath:sql/create-schema.sql", "classpath:sql/insert-user-data.sql"}, diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/controller/TestController.java b/apps/user-service/src/test/java/com/gltkorea/icebang/controller/TestController.java new file mode 100644 index 00000000..c29707ce --- /dev/null +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/controller/TestController.java @@ -0,0 +1,15 @@ +package com.gltkorea.icebang.controller; + +import org.springframework.boot.test.context.TestComponent; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@TestComponent +@RestController +public class TestController { + + @GetMapping("/api/health") + public String health() { + return "OK"; + } +} diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/support/E2eTestSupportTest.java b/apps/user-service/src/test/java/com/gltkorea/icebang/support/E2eTestSupportTest.java new file mode 100644 index 00000000..41c24bf0 --- /dev/null +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/support/E2eTestSupportTest.java @@ -0,0 +1,31 @@ +package com.gltkorea.icebang.support; + +import static org.assertj.core.api.Assertions.assertThat; + +import org.junit.jupiter.api.Test; +import org.springframework.test.context.jdbc.Sql; + +@Sql(scripts = "classpath:sql/create-users-entity.sql") +class E2eTestSupportTest extends E2eTestSupport { + + @Test + void shouldStartWithRandomPort() { + // 포트가 제대로 할당되었는지 확인 + assertThat(port).isGreaterThan(0); + assertThat(getBaseUrl()).startsWith("http://localhost:"); + assertThat(getApiUrl("/test")).contains("/api/test"); + } + + @Test + void shouldHaveRestTemplate() { + // RestTemplate이 주입되었는지 확인 + assertThat(restTemplate).isNotNull(); + } + + @Test + void shouldConnectToMariaDBContainer() { + // 실제 DB 연결 확인 + String response = restTemplate.getForObject(getApiUrl("/health"), String.class); + // health check endpoint가 있다면 사용, 없으면 간단한 컨트롤러 만들어서 테스트 + } +} diff --git a/apps/user-service/src/test/java/com/gltkorea/icebang/support/UnitTestSupportTest.java b/apps/user-service/src/test/java/com/gltkorea/icebang/support/UnitTestSupportTest.java new file mode 100644 index 00000000..232a2c1f --- /dev/null +++ b/apps/user-service/src/test/java/com/gltkorea/icebang/support/UnitTestSupportTest.java @@ -0,0 +1,41 @@ +package com.gltkorea.icebang.support; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +import javax.sql.DataSource; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +class UnitTestSupportTest extends UnitTestSupport { + + @Autowired private DataSource dataSource; + + @Test + void shouldUseH2DatabaseWithMariaDBMode() throws SQLException { + try (Connection connection = dataSource.getConnection()) { + String url = connection.getMetaData().getURL(); + assertThat(url).contains("h2:mem:testdb"); + + // MariaDB 모드 확인 + Statement stmt = connection.createStatement(); + ResultSet rs = + stmt.executeQuery( + "SELECT SETTING_VALUE FROM INFORMATION_SCHEMA.SETTINGS WHERE SETTING_NAME = 'MODE'"); + if (rs.next()) { + assertThat(rs.getString(1)).isEqualTo("MariaDB"); + } + } + } + + @Test + void shouldLoadApplicationContext() { + // Spring Context 로딩 확인 + assertThat(dataSource).isNotNull(); + } +} diff --git a/apps/user-service/src/test/resources/sql/create-users-entity.sql b/apps/user-service/src/test/resources/sql/create-users-entity.sql index 62f32ce7..e36805fc 100644 --- a/apps/user-service/src/test/resources/sql/create-users-entity.sql +++ b/apps/user-service/src/test/resources/sql/create-users-entity.sql @@ -1,5 +1,5 @@ -- MariaDB 최적화된 스키마 (소문자, VARCHAR 크기 지정) -CREATE TABLE `permissions` ( +CREATE TABLE IF NOT EXISTS `permissions` ( `id` int unsigned NOT NULL AUTO_INCREMENT, `resource` varchar(100) NULL, `description` varchar(255) NULL, @@ -11,7 +11,7 @@ CREATE TABLE `permissions` ( PRIMARY KEY (`id`) ); -CREATE TABLE `organizations` ( +CREATE TABLE IF NOT EXISTS `organizations` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(150) NULL, `domain_name` varchar(100) NULL, @@ -20,7 +20,7 @@ CREATE TABLE `organizations` ( PRIMARY KEY (`id`) ); -CREATE TABLE `roles` ( +CREATE TABLE IF NOT EXISTS `roles` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `organization_id` bigint unsigned NULL, `name` varchar(100) NULL, @@ -30,7 +30,7 @@ CREATE TABLE `roles` ( REFERENCES `organizations` (`id`) ON DELETE SET NULL ); -CREATE TABLE `users` ( +CREATE TABLE IF NOT EXISTS `users` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `name` varchar(50) NULL, `email` varchar(100) NULL, @@ -41,7 +41,7 @@ CREATE TABLE `users` ( PRIMARY KEY (`id`) ); -CREATE TABLE `departments` ( +CREATE TABLE IF NOT EXISTS `departments` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `organization_id` bigint unsigned NOT NULL, `name` varchar(100) NULL, @@ -49,7 +49,7 @@ CREATE TABLE `departments` ( CONSTRAINT `fk_organizations_to_departments` FOREIGN KEY (`organization_id`) REFERENCES `organizations` (`id`) ); -CREATE TABLE `positions` ( +CREATE TABLE IF NOT EXISTS `positions` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `organization_id` bigint unsigned NOT NULL, `title` varchar(100) NULL, @@ -57,7 +57,7 @@ CREATE TABLE `positions` ( CONSTRAINT `fk_organizations_to_positions` FOREIGN KEY (`organization_id`) REFERENCES `organizations` (`id`) ); -CREATE TABLE `user_organizations` ( +CREATE TABLE IF NOT EXISTS `user_organizations` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `user_id` bigint unsigned NOT NULL, `organization_id` bigint unsigned NOT NULL, @@ -74,7 +74,7 @@ CREATE TABLE `user_organizations` ( CONSTRAINT `fk_departments_to_user_organizations` FOREIGN KEY (`department_id`) REFERENCES `departments` (`id`) ); -CREATE TABLE `role_permissions` ( +CREATE TABLE IF NOT EXISTS `role_permissions` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `role_id` bigint unsigned NOT NULL, `permission_id` int unsigned NOT NULL, @@ -84,7 +84,7 @@ CREATE TABLE `role_permissions` ( UNIQUE KEY `uk_role_permission` (`role_id`, `permission_id`) ); -CREATE TABLE `user_roles` ( +CREATE TABLE IF NOT EXISTS `user_roles` ( `id` bigint unsigned NOT NULL AUTO_INCREMENT, `role_id` bigint unsigned NOT NULL, `user_organization_id` bigint unsigned NOT NULL, @@ -95,11 +95,19 @@ CREATE TABLE `user_roles` ( ); -- 성능 최적화를 위한 인덱스 -CREATE INDEX `idx_users_email` ON `users` (`email`); -CREATE INDEX `idx_users_status` ON `users` (`status`); -CREATE INDEX `idx_user_organizations_user` ON `user_organizations` (`user_id`); -CREATE INDEX `idx_user_organizations_org` ON `user_organizations` (`organization_id`); -CREATE INDEX `idx_user_organizations_status` ON `user_organizations` (`status`); -CREATE INDEX `idx_roles_org` ON `roles` (`organization_id`); -CREATE INDEX `idx_permissions_resource` ON `permissions` (`resource`); -CREATE INDEX `idx_permissions_active` ON `permissions` (`is_active`); \ No newline at end of file +CREATE INDEX IF NOT EXISTS + `idx_users_email` ON `users` (`email`); +CREATE INDEX IF NOT EXISTS + `idx_users_status` ON `users` (`status`); +CREATE INDEX IF NOT EXISTS + `idx_user_organizations_user` ON `user_organizations` (`user_id`); +CREATE INDEX IF NOT EXISTS + `idx_user_organizations_org` ON `user_organizations` (`organization_id`); +CREATE INDEX IF NOT EXISTS + `idx_user_organizations_status` ON `user_organizations` (`status`); +CREATE INDEX IF NOT EXISTS + `idx_roles_org` ON `roles` (`organization_id`); +CREATE INDEX IF NOT EXISTS + `idx_permissions_resource` ON `permissions` (`resource`); +CREATE INDEX IF NOT EXISTS + `idx_permissions_active` ON `permissions` (`is_active`); \ No newline at end of file