From 729e3e8c45cbb61c6a9847be02a17c08c9f46db6 Mon Sep 17 00:00:00 2001 From: Klaus Date: Sun, 12 Jul 2026 21:16:58 +0900 Subject: [PATCH] =?UTF-8?q?docs(coupon):=20=EC=BA=94=20=EC=BF=A0=ED=8F=B0?= =?UTF-8?q?=20OSIV=20=ED=9A=8C=EA=B7=80=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EA=B3=84=ED=9A=8D=EC=9D=84=20=EB=AC=B8=EC=84=9C=ED=99=94?= =?UTF-8?q?=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plan-task.md | 30 +++++++++++++++++++ .../20260712_캔쿠폰_OSIV회귀테스트보강/prd.md | 24 +++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 docs/20260712_캔쿠폰_OSIV회귀테스트보강/plan-task.md create mode 100644 docs/20260712_캔쿠폰_OSIV회귀테스트보강/prd.md diff --git a/docs/20260712_캔쿠폰_OSIV회귀테스트보강/plan-task.md b/docs/20260712_캔쿠폰_OSIV회귀테스트보강/plan-task.md new file mode 100644 index 00000000..518cd3ba --- /dev/null +++ b/docs/20260712_캔쿠폰_OSIV회귀테스트보강/plan-task.md @@ -0,0 +1,30 @@ +# 캔 쿠폰 OSIV 회귀 테스트 보강 Plan/TASK + +## Goal +`CanCouponService.useCanCoupon()`가 OSIV off 환경에서 Spring 트랜잭션 프록시를 통해 호출될 때 `Member.auth` lazy 연관 접근을 포함한 쿠폰 사용 흐름이 예외 없이 완료됨을 검증한다. + +### Phase 1: 실제 호출 경로 통합 테스트 추가 + +- [x] **Task 1.1: `CanCouponServiceIntegrationTest` 추가** + - 파일: `src/test/kotlin/kr/co/vividnext/sodalive/can/coupon/CanCouponServiceIntegrationTest.kt` + - RED: 트랜잭션 없는 테스트 메서드에서 인증 회원, lazy `Member.auth`, CAN 쿠폰 fixture를 만든 뒤 Spring 빈 `CanCouponService.useCanCoupon()`를 호출하는 테스트를 작성한다. + - GREEN: 기존 `CanCouponService.useCanCoupon()`의 `@Transactional` 경계로 테스트가 통과하는지 확인한다. + - REFACTOR: 테스트 fixture를 최소화하고, 쿠폰 사용 후 저장 상태를 확인한다. + - 검증 기준: + - `./gradlew --no-daemon test --tests kr.co.vividnext.sodalive.can.coupon.CanCouponServiceIntegrationTest` + - `./gradlew --no-daemon ktlintCheck` + - 검증 기록: + - 무엇: `CanCouponServiceIntegrationTest`에서 인증 회원, lazy `Member.auth`, CAN 쿠폰 fixture를 DB에 저장한 뒤 트랜잭션 없는 테스트 메서드에서 Spring 빈 `CanCouponService.useCanCoupon()`를 호출했다. + - 왜: 단순 애노테이션 검사가 아니라 OSIV off 환경의 실제 서비스 호출 경로에서 lazy 초기화 예외가 재발하지 않는지 확인하기 위해서다. + - 어떻게: 첫 실행 `./gradlew --no-daemon test --tests kr.co.vividnext.sodalive.can.coupon.CanCouponServiceIntegrationTest`는 컨텍스트 부팅 중 Redis 연결 실패로 실패했다. 테스트에 기존 관례인 `EmbeddedRedisInitializer` opt-in과 `@DirtiesContext`를 추가했다. + - 결과: 재실행 `./gradlew --no-daemon test --tests kr.co.vividnext.sodalive.can.coupon.CanCouponServiceIntegrationTest`가 `BUILD SUCCESSFUL in 2m 1s`로 통과했다. + +## 검증 기록 +- Run: `./gradlew --no-daemon test --tests kr.co.vividnext.sodalive.can.coupon.CanCouponServiceTest --tests kr.co.vividnext.sodalive.can.coupon.CanCouponServiceIntegrationTest` +- Result: `BUILD SUCCESSFUL in 2m 24s` +- Run: `./gradlew --no-daemon ktlintCheck` +- Result: `BUILD SUCCESSFUL in 1m 9s` +- Run: `git diff --check` +- Result: 공백 오류 없이 통과 +- Run: `./gradlew tasks --all` +- Result: sandbox 환경에서는 `~/.gradle` wrapper lock 파일 접근 제한으로 실패했고, 승인 실행 후 `BUILD SUCCESSFUL in 11s`로 통과했다. diff --git a/docs/20260712_캔쿠폰_OSIV회귀테스트보강/prd.md b/docs/20260712_캔쿠폰_OSIV회귀테스트보강/prd.md new file mode 100644 index 00000000..4fa0cfcd --- /dev/null +++ b/docs/20260712_캔쿠폰_OSIV회귀테스트보강/prd.md @@ -0,0 +1,24 @@ +# PRD: 캔 쿠폰 OSIV 회귀 테스트 보강 + +## 1. Overview +`CanCouponService.useCanCoupon()`가 `spring.jpa.open-in-view=false` 환경에서도 실제 Spring 호출 경로에서 lazy 초기화 예외 없이 동작하는지 검증하는 통합 테스트를 추가한다. + +## 2. Problem +- 기존 단위 테스트는 `@Transactional` 애노테이션 존재만 확인한다. +- 실제 DB 엔티티, Spring 트랜잭션 프록시, lazy 연관 접근이 함께 동작하는지는 검증하지 못한다. +- `Member.auth` lazy 연관 접근이 다시 트랜잭션 밖에서 실행되면 `LazyInitializationException` 회귀가 발생할 수 있다. + +## 3. Goals +- 트랜잭션 없는 테스트 메서드에서 Spring 빈 `CanCouponService.useCanCoupon()`를 호출한다. +- 인증된 회원의 `member.auth` lazy 연관을 포함한 실제 쿠폰 사용 경로가 예외 없이 완료됨을 검증한다. +- 쿠폰 사용 후 회원 보상 캔과 쿠폰 사용 회원이 저장됐는지 확인한다. + +## 4. Non-Goals +- 공개 API 스키마 변경은 하지 않는다. +- 쿠폰 사용 정책이나 충전 정책 로직은 변경하지 않는다. +- 전체 OSIV 회귀 테스트를 재구성하지 않는다. + +## 5. Technical Constraints +- 기존 Kotlin/Spring Boot 테스트 스타일을 따른다. +- `spring.jpa.open-in-view=false` 테스트 설정을 유지한다. +- 검증 범위는 캔 쿠폰 사용 실제 호출 경로로 제한한다.