55import com .back .domain .level .service .LevelUpService ;
66import com .back .domain .member .entity .Member ;
77import com .back .domain .member .repository .MemberRepository ;
8+ import com .back .domain .reward .entity .ContentType ;
9+ import com .back .domain .reward .entity .Reward ;
10+ import com .back .domain .reward .entity .RewardContent ;
11+ import com .back .domain .reward .entity .RewardType ;
812import com .back .domain .reward .repository .RewardRepository ;
13+ import com .back .domain .title .dto .CreateTitleDto ;
14+ import com .back .domain .title .dto .TitleDto ;
15+ import com .back .domain .title .service .TitleService ;
916import org .junit .jupiter .api .BeforeEach ;
1017import org .junit .jupiter .api .DisplayName ;
1118import org .junit .jupiter .api .Test ;
1219import org .springframework .beans .factory .annotation .Autowired ;
1320import org .springframework .boot .test .context .SpringBootTest ;
1421import org .springframework .transaction .annotation .Transactional ;
1522
23+ import java .util .ArrayList ;
24+ import java .util .HashSet ;
25+ import java .util .List ;
1626import java .util .Optional ;
1727
1828import static org .assertj .core .api .Assertions .assertThat ;
@@ -25,7 +35,7 @@ class LevelUpServiceTest {
2535 @ Autowired private MemberRepository memberRepository ;
2636 @ Autowired private LevelXPRepository levelXPRepository ;
2737 @ Autowired private RewardRepository rewardRepository ;
28-
38+ @ Autowired private TitleService titleService ;
2939
3040 // 테스트용 상수 정의
3141 private final int INITIAL_LEVEL = 1 ;
@@ -43,33 +53,54 @@ class LevelUpServiceTest {
4353 // Level 2 달성에 필요한 총 XP (요구치 1500 + 초과분 500 = 2000)
4454 private final int XP_FOR_LEVELUP_AND_EXCESS = XP_TO_LEVEL2 + EXCESS_XP ;
4555
56+ // 테스트용 칭호 ID
57+ private int testTitleId ;
4658
4759 @ BeforeEach
4860 void setupData () {
49- // LevelXP 데이터를 현재 레벨 XP 로직에 맞게 설정
61+ // 모든 데이터 초기화
5062 levelXPRepository .deleteAll ();
63+ rewardRepository .deleteAll ();
5164
52- // Level 1 데이터: Level 2로 가는데 1500 필요
65+ // 1. LevelXP 데이터 설정
5366 levelXPRepository .save (new LevelXP (INITIAL_LEVEL , XP_TO_LEVEL2 ));
54- // Level 2 데이터: Level 3으로 가는데 2000 필요
5567 levelXPRepository .save (new LevelXP (NEXT_LEVEL , XP_TO_LEVEL3 ));
5668
57- // 레벨업 보상 지급 로직을 회피하기 위해 Reward 데이터를 삭제합니다.
58- rewardRepository .deleteAll ();
69+ // 2. 테스트용 칭호 생성 및 ID 저장
70+ TitleDto createdTitle = titleService .createTitle (new CreateTitleDto ("테스트 칭호" , "레벨 2 달성" , "테스트용 캡션" ));
71+ testTitleId = createdTitle .id ();
72+
73+ // 3. LevelUp Reward 데이터 설정
74+ List <RewardContent > titleRewardContents = new ArrayList <>();
75+ titleRewardContents .add (new RewardContent (ContentType .TITLE , testTitleId ));
76+
77+ // Level 2 달성을 요구하는 LEVELUP 보상 생성 (requireValue: 2)
78+ Reward reward = new Reward (RewardType .LEVELUP , titleRewardContents , NEXT_LEVEL );
79+ rewardRepository .save (reward );
80+ }
81+
82+ private Member createTestMember (int level , int xp , int xpReq ) {
83+ Member member = Member .builder ()
84+ .level (level )
85+ .xp (xp )
86+ .xpReq (xpReq )
87+ .money (0 )
88+ .build ();
89+ if (member .getOwnedTitles () == null ) {
90+ member .setOwnedTitles (new HashSet <>());
91+ }
92+ if (member .getOwnedItems () == null ) {
93+ member .setOwnedItems (new HashSet <>());
94+ }
95+ return memberRepository .save (member );
5996 }
6097
6198
6299 @ Test
63100 @ DisplayName ("XP 요구치 충족 시 레벨업이 발생하고, 초과 경험치가 다음 레벨로 이월되며, 다음 xpReq가 업데이트된다" )
64101 void checkLevelUp_ShouldLevelUp_WithExcessXP () {
65102 // GIVEN
66- Member member = Member .builder ()
67- .level (INITIAL_LEVEL )
68- .xp (INITIAL_XP ) // INITIAL_XP = 0
69- .xpReq (XP_TO_LEVEL2 ) // Level 2 요구 XP
70- .money (0 ) // 돈은 검증 대상이 아님
71- .build ();
72- member = memberRepository .save (member );
103+ Member member = createTestMember (INITIAL_LEVEL , INITIAL_XP , XP_TO_LEVEL2 );
73104 Integer memberId = member .getId ();
74105
75106 // 레벨업에 충분한 XP를 수동으로 설정
@@ -93,17 +124,47 @@ void checkLevelUp_ShouldLevelUp_WithExcessXP() {
93124 }
94125
95126
127+ @ Test
128+ @ DisplayName ("XP 요구치 충족 시 레벨업이 발생하고, 레벨업 보상으로 칭호가 제대로 지급된다" )
129+ void checkLevelUp_ShouldLevelUp_AndGiveTitleReward () {
130+ // GIVEN
131+ Member member = createTestMember (INITIAL_LEVEL , INITIAL_XP , XP_TO_LEVEL2 );
132+ Integer memberId = member .getId ();
133+
134+ // 초기에는 칭호를 가지고 있지 않아야 합니다.
135+ assertThat (member .getOwnedTitles ()).isEmpty ();
136+
137+ // 레벨업에 충분한 XP를 수동으로 설정
138+ member .setXp (XP_FOR_LEVELUP_AND_EXCESS ); // member.xp = 2000
139+ memberRepository .save (member );
140+
141+ // WHEN
142+ levelUpService .checkLevelUp (memberId );
143+
144+ // THEN
145+ Optional <Member > updatedMemberOpt = memberRepository .findById (memberId );
146+ assertThat (updatedMemberOpt ).isPresent ();
147+ Member updatedMember = updatedMemberOpt .get ();
148+
149+ // 1. 레벨업 확인
150+ assertThat (updatedMember .getLevel ()).isEqualTo (NEXT_LEVEL ); // Level 2로 레벨업
151+
152+ // 2. 칭호 지급 확인 (핵심 검증)
153+ // 획득한 칭호 Set이 비어있지 않고, 그 크기가 1인지 확인
154+ assertThat (updatedMember .getOwnedTitles ()).hasSize (1 );
155+
156+ // 획득한 칭호의 ID가 테스트용으로 생성한 칭호 ID와 일치하는지 확인
157+ assertThat (updatedMember .getOwnedTitles ().stream ().anyMatch (title -> title .getId () == testTitleId )).isTrue ();
158+
159+ // 3. XP 이월 확인
160+ assertThat (updatedMember .getXp ()).isEqualTo (EXCESS_XP );
161+ }
162+
96163 @ Test
97164 @ DisplayName ("XP가 레벨업 요구치에 미달하면 레벨 및 XP 변화가 없다" )
98165 void checkLevelUp_ShouldNotLevelUp_NoChange () {
99166 // GIVEN
100- Member member = Member .builder ()
101- .level (INITIAL_LEVEL )
102- .xp (INITIAL_XP )
103- .xpReq (XP_TO_LEVEL2 )
104- .money (0 )
105- .build ();
106- member = memberRepository .save (member );
167+ Member member = createTestMember (INITIAL_LEVEL , INITIAL_XP , XP_TO_LEVEL2 );
107168 Integer memberId = member .getId ();
108169
109170 // 레벨업에 부족한 XP를 설정 (요구치 1500 미만인 1499 설정)
@@ -129,17 +190,10 @@ void checkLevelUp_ShouldNotLevelUp_NoChange() {
129190 @ DisplayName ("충분한 XP를 부여하여 다중 레벨업이 연속적으로 발생하고, 최종 XP가 이월된다" )
130191 void checkLevelUp_ShouldHandleMultipleLevelUps () {
131192 // GIVEN
132-
133193 // Level 1 -> 2 -> 3 연속 레벨업을 위한 충분한 XP 계산
134194 int totalXpForMultipleLevelUp = XP_TO_LEVEL2 + XP_TO_LEVEL3 + EXCESS_XP ; // 1500 + 2000 + 500 = 4000
135195
136- Member member = Member .builder ()
137- .level (INITIAL_LEVEL )
138- .xp (INITIAL_XP )
139- .xpReq (XP_TO_LEVEL2 )
140- .money (0 )
141- .build ();
142- member = memberRepository .save (member );
196+ Member member = createTestMember (INITIAL_LEVEL , INITIAL_XP , XP_TO_LEVEL2 );
143197 Integer memberId = member .getId ();
144198
145199 member .setXp (totalXpForMultipleLevelUp ); // member.xp = 4000
@@ -165,5 +219,4 @@ void checkLevelUp_ShouldHandleMultipleLevelUps() {
165219 // 3. 다음 요구 XP 확인
166220 assertThat (updatedMember .getXpReq ()).isEqualTo (XP_TO_LEVEL4 ); // Level 4 요구량
167221 }
168-
169222}
0 commit comments