1919import com .swyp .picke .domain .vote .dto .response .VoteResultResponse ;
2020import com .swyp .picke .domain .vote .entity .BattleVote ;
2121import com .swyp .picke .domain .vote .repository .BattleVoteRepository ;
22+ import java .time .LocalDate ;
2223import java .util .Optional ;
2324import org .junit .jupiter .api .DisplayName ;
2425import org .junit .jupiter .api .Test ;
2526import org .junit .jupiter .api .extension .ExtendWith ;
2627import org .mockito .InjectMocks ;
2728import org .mockito .Mock ;
2829import org .mockito .junit .jupiter .MockitoExtension ;
30+ import org .springframework .context .ApplicationEventPublisher ;
2931import org .springframework .test .util .ReflectionTestUtils ;
3032
3133import static org .assertj .core .api .Assertions .assertThat ;
34+ import static org .mockito .Mockito .never ;
3235import static org .mockito .Mockito .verify ;
3336import static org .mockito .Mockito .when ;
3437
@@ -53,13 +56,84 @@ class BattleVoteServiceImplTest {
5356 @ Mock
5457 private CreditService creditService ;
5558
59+ @ Mock
60+ private ApplicationEventPublisher eventPublisher ;
61+
5662 @ InjectMocks
5763 private BattleVoteServiceImpl battleVoteService ;
5864
65+ @ Test
66+ @ DisplayName ("오늘 배틀이 아니면 최초 사전 투표 시 BATTLE_ENTRY 크레딧을 차감한다" )
67+ void preVote_chargesBattleEntryCreditForPastBattle () {
68+ Battle battle = battle (100L , LocalDate .now ().minusDays (1 ));
69+ User user = user (10L );
70+ BattleOption option = option (201L , battle , BattleOptionLabel .A );
71+
72+ when (battleService .findById (100L )).thenReturn (battle );
73+ when (userRepository .findById (10L )).thenReturn (Optional .of (user ));
74+ when (battleOptionRepository .findById (201L )).thenReturn (Optional .of (option ));
75+ when (battleVoteRepository .findByBattleAndUser (battle , user )).thenReturn (Optional .empty ());
76+ when (userBattleService .getUserBattleStatus (user , battle ))
77+ .thenReturn (new UserBattleStatusResponse (100L , UserBattleStep .NONE ));
78+
79+ VoteResultResponse response = battleVoteService .preVote (100L , 10L , new VoteRequest (201L ));
80+
81+ assertThat (response .status ()).isEqualTo (UserBattleStep .PRE_VOTE );
82+ verify (creditService ).addCredit (10L , CreditType .BATTLE_ENTRY , 100L );
83+ verify (userBattleService ).upsertStep (user , battle , UserBattleStep .PRE_VOTE );
84+ }
85+
86+ @ Test
87+ @ DisplayName ("오늘 배틀이면 최초 사전 투표 시 크레딧을 차감하지 않는다" )
88+ void preVote_doesNotChargeBattleEntryCreditForTodayBattle () {
89+ Battle battle = battle (100L , LocalDate .now ());
90+ User user = user (10L );
91+ BattleOption option = option (201L , battle , BattleOptionLabel .A );
92+
93+ when (battleService .findById (100L )).thenReturn (battle );
94+ when (userRepository .findById (10L )).thenReturn (Optional .of (user ));
95+ when (battleOptionRepository .findById (201L )).thenReturn (Optional .of (option ));
96+ when (battleVoteRepository .findByBattleAndUser (battle , user )).thenReturn (Optional .empty ());
97+ when (userBattleService .getUserBattleStatus (user , battle ))
98+ .thenReturn (new UserBattleStatusResponse (100L , UserBattleStep .NONE ));
99+
100+ VoteResultResponse response = battleVoteService .preVote (100L , 10L , new VoteRequest (201L ));
101+
102+ assertThat (response .status ()).isEqualTo (UserBattleStep .PRE_VOTE );
103+ verify (creditService , never ()).addCredit (10L , CreditType .BATTLE_ENTRY , 100L );
104+ }
105+
106+ @ Test
107+ @ DisplayName ("이미 사전 투표한 배틀이면 옵션 변경 시 추가 차감하지 않는다" )
108+ void preVote_doesNotChargeAgainWhenVoteAlreadyExists () {
109+ Battle battle = battle (100L , LocalDate .now ().minusDays (1 ));
110+ User user = user (10L );
111+ BattleOption oldOption = option (200L , battle , BattleOptionLabel .B );
112+ BattleOption newOption = option (201L , battle , BattleOptionLabel .A );
113+ BattleVote vote = BattleVote .builder ()
114+ .user (user )
115+ .battle (battle )
116+ .preVoteOption (oldOption )
117+ .build ();
118+
119+ when (battleService .findById (100L )).thenReturn (battle );
120+ when (userRepository .findById (10L )).thenReturn (Optional .of (user ));
121+ when (battleOptionRepository .findById (201L )).thenReturn (Optional .of (newOption ));
122+ when (battleVoteRepository .findByBattleAndUser (battle , user )).thenReturn (Optional .of (vote ));
123+ when (userBattleService .getUserBattleStatus (user , battle ))
124+ .thenReturn (new UserBattleStatusResponse (100L , UserBattleStep .PRE_VOTE ));
125+
126+ VoteResultResponse response = battleVoteService .preVote (100L , 10L , new VoteRequest (201L ));
127+
128+ assertThat (response .status ()).isEqualTo (UserBattleStep .PRE_VOTE );
129+ assertThat (vote .getPreVoteOption ()).isEqualTo (newOption );
130+ verify (creditService , never ()).addCredit (10L , CreditType .BATTLE_ENTRY , 100L );
131+ }
132+
59133 @ Test
60134 @ DisplayName ("사후 투표 완료 시 참여 보상 크레딧을 지급한다" )
61135 void postVote_rewardsBattleParticipationCredit () {
62- Battle battle = battle (100L );
136+ Battle battle = battle (100L , null );
63137 User user = user (10L );
64138 BattleOption preOption = option (201L , battle , BattleOptionLabel .A );
65139 BattleOption postOption = option (202L , battle , BattleOptionLabel .B );
@@ -86,10 +160,11 @@ void postVote_rewardsBattleParticipationCredit() {
86160 verify (creditService ).addCredit (10L , CreditType .BATTLE_VOTE , 300L );
87161 }
88162
89- private Battle battle (Long id ) {
163+ private Battle battle (Long id , LocalDate targetDate ) {
90164 Battle battle = Battle .builder ()
91165 .title ("battle" )
92166 .summary ("summary" )
167+ .targetDate (targetDate )
93168 .status (BattleStatus .PUBLISHED )
94169 .build ();
95170 ReflectionTestUtils .setField (battle , "id" , id );
0 commit comments