From c0b0340fd8b7437635fca46933dfa27c26f78cf9 Mon Sep 17 00:00:00 2001 From: Roy Date: Wed, 2 Sep 2026 16:29:17 +0900 Subject: [PATCH] =?UTF-8?q?#440=20[Fix]=20BattleVoteServiceImplTest=20?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=EB=8C=80=20=EB=B6=88=EC=9D=BC=EC=B9=98?= =?UTF-8?q?=EB=A1=9C=2015=EC=8B=9C(UTC)=20=EC=9D=B4=ED=9B=84=20CI=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BattleVoteServiceImpl은 "오늘"을 LocalDate.now(KST)로 판단하는데 테스트는 시스템 기본 시간대의 LocalDate.now()를 썼다. UTC 러너에서는 15:00 UTC(=KST 자정) 이후로 두 값이 하루씩 어긋나 오늘 배틀이 어제 배틀로 취급되면서 크레딧 차감 분기가 반대로 탔다. 같은 브랜치에서 14:42 UTC 실행은 통과하고 15:25 UTC 실행은 실패했다. 테스트도 KST 기준으로 맞춘다. --- .../service/BattleVoteServiceImplTest.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImplTest.java b/src/test/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImplTest.java index 545207c..e876aef 100644 --- a/src/test/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImplTest.java +++ b/src/test/java/com/swyp/picke/domain/vote/service/BattleVoteServiceImplTest.java @@ -26,6 +26,7 @@ import com.swyp.picke.domain.vote.entity.BattleVote; import com.swyp.picke.domain.vote.repository.BattleVoteRepository; import java.time.LocalDate; +import java.time.ZoneId; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.DisplayName; @@ -75,10 +76,20 @@ class BattleVoteServiceImplTest { @InjectMocks private BattleVoteServiceImpl battleVoteService; + /** + * BattleVoteServiceImpl은 "오늘"을 KST로 판단한다(LocalDate.now(KST)). + * 테스트가 시스템 기본 시간대를 쓰면 UTC 러너에서 15시 이후로 하루가 어긋나 실패한다. + */ + private static final ZoneId KST = ZoneId.of("Asia/Seoul"); + + private static LocalDate today() { + return LocalDate.now(KST); + } + @Test @DisplayName("오늘 배틀이 아니면 최초 사전 투표 시 BATTLE_ENTRY 크레딧을 차감한다") void preVote_chargesBattleEntryCreditForPastBattle() { - Battle battle = battle(100L, LocalDate.now().minusDays(1)); + Battle battle = battle(100L, today().minusDays(1)); User user = user(10L); BattleOption option = option(201L, battle, BattleOptionLabel.A); @@ -99,7 +110,7 @@ void preVote_chargesBattleEntryCreditForPastBattle() { @Test @DisplayName("오늘 배틀이면 최초 사전 투표 시 크레딧을 차감하지 않는다") void preVote_doesNotChargeBattleEntryCreditForTodayBattle() { - Battle battle = battle(100L, LocalDate.now()); + Battle battle = battle(100L, today()); User user = user(10L); BattleOption option = option(201L, battle, BattleOptionLabel.A); @@ -119,7 +130,7 @@ void preVote_doesNotChargeBattleEntryCreditForTodayBattle() { @Test @DisplayName("오늘의 배틀이라도 오늘 이미 무료 진입을 사용했다면 크레딧을 차감한다") void preVote_chargesBattleEntryCreditWhenFreeEntryAlreadyUsedToday() { - Battle battle = battle(100L, LocalDate.now()); + Battle battle = battle(100L, today()); User user = user(10L); BattleOption option = option(201L, battle, BattleOptionLabel.A); @@ -127,7 +138,7 @@ void preVote_chargesBattleEntryCreditWhenFreeEntryAlreadyUsedToday() { when(userRepository.findById(10L)).thenReturn(Optional.of(user)); when(battleOptionRepository.findById(201L)).thenReturn(Optional.of(option)); when(battleVoteRepository.findByBattleAndUser(battle, user)).thenReturn(Optional.empty()); - when(battleVoteRepository.existsByUserIdAndBattle_TargetDate(10L, LocalDate.now())).thenReturn(true); + when(battleVoteRepository.existsByUserIdAndBattle_TargetDate(10L, today())).thenReturn(true); when(userBattleService.getUserBattleStatus(user, battle)) .thenReturn(new UserBattleStatusResponse(100L, UserBattleStep.NONE)); @@ -140,7 +151,7 @@ void preVote_chargesBattleEntryCreditWhenFreeEntryAlreadyUsedToday() { @Test @DisplayName("이미 사전 투표한 배틀이면 옵션 변경 시 추가 차감하지 않는다") void preVote_doesNotChargeAgainWhenVoteAlreadyExists() { - Battle battle = battle(100L, LocalDate.now().minusDays(1)); + Battle battle = battle(100L, today().minusDays(1)); User user = user(10L); BattleOption oldOption = option(200L, battle, BattleOptionLabel.B); BattleOption newOption = option(201L, battle, BattleOptionLabel.A);