Skip to content

[BE_6] Test Code (test) #205

@pjhcsols

Description

@pjhcsols

어떤 기능인가요?

운영=MySQL / 테스트=H2 완전 분리 구성을 적용했습니다.
운영은 JPA 자동 생성 전략을 유지하고, 테스트는 H2(MySQL 모드)로 구동하면서 배치/부팅 훅 비활성화, 스키마/시드 자동 실행 차단, 로깅/지연초기화 등을 통해 테스트 안정성과 속도를 확보했습니다.


작업 상세 내용

✅ 적용 완료(현재 코드 기준)

  • 테스트 프로필: H2 메모리 + MySQL 호환

    • jdbc:h2:mem:testdb;MODE=MySQL;...;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE
    • username=, driver-class-name=org.h2.Driver
  • JPA DDL 전략(테스트): spring.jpa.hibernate.ddl-auto=create-drop

  • import.sql 자동실행 차단(테스트):
    spring.jpa.properties.hibernate.hbm2ddl.import_files: ""

  • schema.sql / data.sql 자동실행 차단(테스트):
    spring.sql.init.mode=never

  • 불필요 Bean 지연 생성(테스트):
    spring.main.lazy-initialization=true

  • 배치 완전 비활성화(테스트)

    • spring.batch.job.enabled=false
    • spring.batch.jdbc.initialize-schema=never
  • 부팅 훅/배치 러너 차단(테스트): @MockBean으로 숏서킷

    • JobRegistry, JobLauncher, JobRepository, PlatformTransactionManager
    • 잡/스텝 빈(이름): "imageBatchJob", "userImageCleanupStep"
    • 스케줄러: ImageBatchJobScheduler
    • 부팅 러너: @MockBean(name = "runImageBatchOnStartup") ApplicationRunner
    • (보강) 배치 메타 리셋 서비스: BatchSchemaResetService
  • 테스트 컨텍스트 프로필 고정: @ActiveProfiles("test")
    + @SpringBootTest(properties=...)로 배치/지연초기화 재확인

  • P6Spy SLF4J 로깅 사용: decorator.datasource.p6spy.*, logging.level.com.p6spy=INFO

  • 외부 연동 더미 설정 유지(테스트): AWS/JWT/Kakao 값은 테스트에서만 사용(모킹 상태)


📝 선택/권장(향후 개선 항목)

아래는 “필요 시” 진행하세요. 현재 테스트는 data.sql을 자동 실행하지 않도록 설계되어 있어 스키마/시드 오류를 피합니다. 테스트에서 data.sql을 실제로 사용하고 싶다면 A/B 중 택1을 권장합니다.

A. 테스트에서 data.sql 재사용(스키마 접두사 유지 시 권장)

  • H2에 basilium 스키마를 만들고 기본 스키마로 설정
  • JPA DDL 이후 data.sql 실행
# application-test.yml (예시)
spring:
  datasource:
    url: >
      jdbc:h2:mem:testdb;
      MODE=MySQL;
      DATABASE_TO_LOWER=TRUE;
      CASE_INSENSITIVE_IDENTIFIERS=TRUE;
      DB_CLOSE_DELAY=-1;
      DB_CLOSE_ON_EXIT=FALSE;
      INIT=CREATE SCHEMA IF NOT EXISTS basilium\;SET SCHEMA basilium
  jpa:
    hibernate:
      ddl-auto: create-drop
    defer-datasource-initialization: true   # ★ DDL → data.sql 순서 보장
    properties:
      hibernate:
        default_schema: basilium
  sql:
    init:
      mode: always                           # data.sql 자동 실행
      # data-locations: classpath:data-test.sql  # 테스트 전용 시드로 분리 시

B. 테스트 전용 시드로 분리(스키마 접두사 제거)

  • src/test/resources/data-test.sql 작성(테이블명만 사용, basilium. 접두사 제거)
  • 테스트에서만 이 파일을 로딩
spring.sql.init:
  mode: always
  data-locations: classpath:data-test.sql
spring.jpa.defer-datasource-initialization: true

C. 트랜잭션 경계 보강(운영/테스트 공통 품질)

  • @Modifying JPQL/네이티브 업데이트/삭제 쿼리를 서비스 계층에서 @Transactional로 감싸 호출
@Service
public class CouponMaintenanceService {
  @Transactional
  public int activateDueCampaignsNow() {
    return repo.activateDueCampaigns(LocalDateTime.now());
  }
}

D. 배치/스케줄러 코드에 프로퍼티 가드(부트 레벨 차단 외 추가 안전망)

  • 러너/잡에 @ConditionalOnProperty 적용
@ConditionalOnProperty(prefix="jobs.coupon", name="enabled", havingValue="true")
@Component
class CouponMaintenanceJob { ... }

@ConditionalOnProperty(prefix="app.data-init", name="enabled", havingValue="true")
@Bean ApplicationRunner dataInitRunner(...) { ... }

E. 장기 권장

  • 운영 DB 스키마 관리는 Flyway/Liquibase로 전환 로드맵 수립
  • CI에서 테스트 프로필 강제: ./gradlew test -Dspring.profiles.active=test

참고할만한 자료(선택)

  • Spring Boot: SQL initialization (spring.sql.init.*), JPA defer (spring.jpa.defer-datasource-initialization)
  • Spring Data JPA: @Modifying + @Transactional 베스트 프랙티스
  • H2: JDBC URL 옵션(MODE=MySQL, INIT=CREATE SCHEMA…;SET SCHEMA…)
  • Conditional Beans: @Profile, @ConditionalOnProperty

현재 상태: 운영=MySQL 유지 / 테스트=H2 분리, 배치·부팅 훅 차단, 시드 자동실행 차단 까지 적용 완료.
선택 항목은 “테스트에서 실제 data.sql을 쓰고 싶을 때” 또는 “운영 품질(마이그레이션/트랜잭션/가드) 강화를 원할 때” 진행

Metadata

Metadata

Assignees

Labels

feature새로운 기능 추가test

Projects

Status

In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions