-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathMyPageServiceTest.java
More file actions
456 lines (380 loc) · 19.6 KB
/
MyPageServiceTest.java
File metadata and controls
456 lines (380 loc) · 19.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
package com.example.solidconnection.siteuser.service;
import static com.example.solidconnection.common.exception.ErrorCode.CAN_NOT_CHANGE_NICKNAME_YET;
import static com.example.solidconnection.common.exception.ErrorCode.OAUTH_USER_CANNOT_CHANGE_PASSWORD;
import static com.example.solidconnection.common.exception.ErrorCode.PASSWORD_MISMATCH;
import static com.example.solidconnection.siteuser.service.MyPageService.MIN_DAYS_BETWEEN_NICKNAME_CHANGES;
import static com.example.solidconnection.siteuser.service.MyPageService.NICKNAME_LAST_CHANGE_DATE_FORMAT;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.AssertionsForClassTypes.assertThatCode;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.mockito.BDDMockito.any;
import static org.mockito.BDDMockito.eq;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.never;
import static org.mockito.BDDMockito.then;
import com.example.solidconnection.common.exception.CustomException;
import com.example.solidconnection.location.country.domain.Country;
import com.example.solidconnection.location.country.domain.InterestedCountry;
import com.example.solidconnection.location.country.fixture.CountryFixture;
import com.example.solidconnection.location.country.repository.InterestedCountryRepository;
import com.example.solidconnection.location.region.domain.InterestedRegion;
import com.example.solidconnection.location.region.domain.Region;
import com.example.solidconnection.location.region.fixture.RegionFixture;
import com.example.solidconnection.location.region.repository.InterestedRegionRepository;
import com.example.solidconnection.mentor.fixture.MentorFixture;
import com.example.solidconnection.s3.domain.UploadPath;
import com.example.solidconnection.s3.dto.UploadedFileUrlResponse;
import com.example.solidconnection.s3.service.S3Service;
import com.example.solidconnection.siteuser.domain.AuthType;
import com.example.solidconnection.siteuser.domain.Role;
import com.example.solidconnection.siteuser.domain.SiteUser;
import com.example.solidconnection.siteuser.dto.LocationUpdateRequest;
import com.example.solidconnection.siteuser.dto.MyPageResponse;
import com.example.solidconnection.siteuser.dto.PasswordUpdateRequest;
import com.example.solidconnection.siteuser.fixture.SiteUserFixture;
import com.example.solidconnection.siteuser.fixture.SiteUserFixtureBuilder;
import com.example.solidconnection.siteuser.repository.SiteUserRepository;
import com.example.solidconnection.support.TestContainerSpringBootTest;
import com.example.solidconnection.term.domain.Term;
import com.example.solidconnection.term.fixture.TermFixture;
import com.example.solidconnection.university.domain.LikedUnivApplyInfo;
import com.example.solidconnection.university.domain.HostUniversity;
import com.example.solidconnection.university.domain.UnivApplyInfo;
import com.example.solidconnection.university.fixture.UnivApplyInfoFixture;
import com.example.solidconnection.university.repository.LikedUnivApplyInfoRepository;
import java.time.LocalDateTime;
import java.util.List;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.security.crypto.password.PasswordEncoder;
@TestContainerSpringBootTest
@DisplayName("마이페이지 서비스 테스트")
class MyPageServiceTest {
@Autowired
private MyPageService myPageService;
@MockBean
private S3Service s3Service;
@Autowired
private SiteUserRepository siteUserRepository;
@Autowired
private LikedUnivApplyInfoRepository likedUnivApplyInfoRepository;
@Autowired
private InterestedCountryRepository interestedCountryRepository;
@Autowired
private InterestedRegionRepository interestedRegionRepository;
@Autowired
private SiteUserFixture siteUserFixture;
@Autowired
private MentorFixture mentorFixture;
@Autowired
private CountryFixture countryFixture;
@Autowired
private UnivApplyInfoFixture univApplyInfoFixture;
@Autowired
private RegionFixture regionFixture;
@Autowired
private TermFixture termFixture;
@Autowired
private SiteUserFixtureBuilder siteUserFixtureBuilder;
@Autowired
private PasswordEncoder passwordEncoder;
private SiteUser user;
private Term term;
private Long 괌대학_A_지원_정보_ID;
private Long 메이지대학_지원_정보_ID;
private Long 코펜하겐IT대학_지원_정보_ID;
private HostUniversity 괌대학;
@BeforeEach
void setUp() {
user = siteUserFixture.사용자();
term = termFixture.현재_학기("2025-1");
UnivApplyInfo 괌대학_A_지원_정보 = univApplyInfoFixture.괌대학_A_지원_정보(term.getId());
괌대학_A_지원_정보_ID = 괌대학_A_지원_정보.getId();
괌대학 = 괌대학_A_지원_정보.getUniversity();
메이지대학_지원_정보_ID = univApplyInfoFixture.메이지대학_지원_정보(term.getId()).getId();
코펜하겐IT대학_지원_정보_ID = univApplyInfoFixture.코펜하겐IT대학_지원_정보(term.getId()).getId();
}
@Test
void 멘티의_마이페이지_정보를_조회한다() {
// given
int likedUnivApplyInfoCount = createLikedUnivApplyInfos(user);
Country country = countryFixture.미국();
InterestedCountry interestedCountry = new InterestedCountry(user, country);
interestedCountryRepository.save(interestedCountry);
// when
MyPageResponse response = myPageService.getMyPageInfo(user.getId());
// then
assertAll(
() -> assertThat(response.nickname()).isEqualTo(user.getNickname()),
() -> assertThat(response.profileImageUrl()).isEqualTo(user.getProfileImageUrl()),
() -> assertThat(response.role()).isEqualTo(user.getRole()),
() -> assertThat(response.email()).isEqualTo(user.getEmail()),
// () -> assertThat(response.likedPostCount()).isEqualTo(user.getLikedPostList().size()),
// todo : 좋아요한 게시물 수 반환 기능 추가와 함께 수정요망
() -> assertThat(response.likedUnivApplyInfoCount()).isEqualTo(likedUnivApplyInfoCount),
() -> assertThat(response.interestedCountries().get(0)).isEqualTo(country.getKoreanName()),
() -> assertThat(response.attendedUniversity()).isNull()
);
}
@Test
void 멘토의_마이페이지_정보를_조회한다() {
// given
SiteUser mentorUser = siteUserFixture.멘토(1, "mentor");
mentorFixture.멘토(mentorUser.getId(), 괌대학.getId());
int likedUnivApplyInfoCount = createLikedUnivApplyInfos(mentorUser);
// when
MyPageResponse response = myPageService.getMyPageInfo(mentorUser.getId());
// then
assertAll(
() -> assertThat(response.nickname()).isEqualTo(mentorUser.getNickname()),
() -> assertThat(response.profileImageUrl()).isEqualTo(mentorUser.getProfileImageUrl()),
() -> assertThat(response.role()).isEqualTo(mentorUser.getRole()),
() -> assertThat(response.email()).isEqualTo(mentorUser.getEmail()),
// () -> assertThat(response.likedPostCount()).isEqualTo(user.getLikedPostList().size()),
// todo : 좋아요한 게시물 수 반환 기능 추가와 함께 수정요망
() -> assertThat(response.likedUnivApplyInfoCount()).isEqualTo(likedUnivApplyInfoCount),
() -> assertThat(response.attendedUniversity()).isEqualTo(괌대학.getKoreanName()),
() -> assertThat(response.interestedCountries()).isNull()
);
}
private int createLikedUnivApplyInfos(SiteUser testUser) {
LikedUnivApplyInfo likedUnivApplyInfo1 = new LikedUnivApplyInfo(null, 괌대학_A_지원_정보_ID, testUser.getId());
LikedUnivApplyInfo likedUnivApplyInfo2 = new LikedUnivApplyInfo(null, 메이지대학_지원_정보_ID, testUser.getId());
LikedUnivApplyInfo likedUnivApplyInfo3 = new LikedUnivApplyInfo(null, 코펜하겐IT대학_지원_정보_ID, testUser.getId());
likedUnivApplyInfoRepository.save(likedUnivApplyInfo1);
likedUnivApplyInfoRepository.save(likedUnivApplyInfo2);
likedUnivApplyInfoRepository.save(likedUnivApplyInfo3);
return likedUnivApplyInfoRepository.countBySiteUserId(testUser.getId());
}
private MockMultipartFile createValidImageFile() {
return new MockMultipartFile(
"image",
"test.jpg",
"image/jpeg",
"test image content".getBytes()
);
}
private String createExpectedErrorMessage(LocalDateTime modifiedAt) {
String formatLastModifiedAt = String.format(
"(마지막 수정 시간 : %s)",
NICKNAME_LAST_CHANGE_DATE_FORMAT.format(modifiedAt)
);
return CAN_NOT_CHANGE_NICKNAME_YET.getMessage() + " : " + formatLastModifiedAt;
}
private SiteUser createSiteUserWithCustomProfile() {
return siteUserFixtureBuilder.siteUser()
.email("customProfile@example.com")
.authType(AuthType.EMAIL)
.nickname("커스텀프로필")
.profileImageUrl("profile/profileImageUrl")
.role(Role.MENTEE)
.password("customPassword123")
.create();
}
@Nested
class 프로필_이미지_수정_테스트 {
@Test
void 새로운_이미지로_성공적으로_업데이트한다() {
// given
String expectedUrl = "newProfileImageUrl";
MockMultipartFile imageFile = createValidImageFile();
given(s3Service.uploadFile(any(), eq(UploadPath.PROFILE)))
.willReturn(new UploadedFileUrlResponse(expectedUrl));
// when
myPageService.updateMyPageInfo(user.getId(), imageFile, "newNickname");
// then
SiteUser updatedUser = siteUserRepository.findById(user.getId()).get();
assertThat(updatedUser.getProfileImageUrl()).isEqualTo(expectedUrl);
}
@Test
void 프로필을_처음_수정하는_것이면_이전_이미지를_삭제하지_않는다() {
// given
MockMultipartFile imageFile = createValidImageFile();
given(s3Service.uploadFile(any(), eq(UploadPath.PROFILE)))
.willReturn(new UploadedFileUrlResponse("newProfileImageUrl"));
// when
myPageService.updateMyPageInfo(user.getId(), imageFile, "newNickname");
// then
then(s3Service).should(never()).deleteExProfile(user.getId());
}
@Test
void 프로필을_처음_수정하는_것이_아니라면_이전_이미지를_삭제한다() {
// given
SiteUser 커스텀_프로필_사용자 = createSiteUserWithCustomProfile();
MockMultipartFile imageFile = createValidImageFile();
given(s3Service.uploadFile(any(), eq(UploadPath.PROFILE)))
.willReturn(new UploadedFileUrlResponse("newProfileImageUrl"));
// when
myPageService.updateMyPageInfo(커스텀_프로필_사용자.getId(), imageFile, "newNickname");
// then
then(s3Service).should().deleteExProfile(커스텀_프로필_사용자.getId());
}
}
@Nested
class 닉네임_수정_테스트 {
@BeforeEach
void setUp() {
given(s3Service.uploadFile(any(), eq(UploadPath.PROFILE)))
.willReturn(new UploadedFileUrlResponse("newProfileImageUrl"));
}
@Test
void 닉네임을_성공적으로_수정한다() {
// given
MockMultipartFile imageFile = createValidImageFile();
String newNickname = "newNickname";
// when
myPageService.updateMyPageInfo(user.getId(), imageFile, newNickname);
// then
SiteUser updatedUser = siteUserRepository.findById(user.getId()).get();
assertThat(updatedUser.getNicknameModifiedAt()).isNotNull();
assertThat(updatedUser.getNickname()).isEqualTo(newNickname);
}
@Test
void 최소_대기기간이_지나지_않은_상태에서_변경하면_예외가_발생한다() {
// given
MockMultipartFile imageFile = createValidImageFile();
LocalDateTime modifiedAt = LocalDateTime.now().minusDays(MIN_DAYS_BETWEEN_NICKNAME_CHANGES - 1);
user.setNicknameModifiedAt(modifiedAt);
siteUserRepository.save(user);
// when & then
assertThatCode(() -> myPageService.updateMyPageInfo(user.getId(), imageFile, "nickname12"))
.isInstanceOf(CustomException.class)
.hasMessage(createExpectedErrorMessage(modifiedAt));
}
}
@Nested
class 비밀번호_변경_테스트 {
private String currentPassword;
private String newPassword;
@BeforeEach
void setUp() {
currentPassword = "currentPassword123";
newPassword = "newPassword123";
user.updatePassword(passwordEncoder.encode(currentPassword));
siteUserRepository.save(user);
}
@Test
void 비밀번호를_성공적으로_변경한다() {
// given
PasswordUpdateRequest request = new PasswordUpdateRequest(currentPassword, newPassword, newPassword);
// when
myPageService.updatePassword(user.getId(), request);
// then
SiteUser updatedUser = siteUserRepository.findById(user.getId()).get();
assertAll(
() -> assertThat(passwordEncoder.matches(newPassword, updatedUser.getPassword())).isTrue(),
() -> assertThat(passwordEncoder.matches(currentPassword, updatedUser.getPassword())).isFalse()
);
}
@Test
void 현재_비밀번호가_일치하지_않으면_예외가_발생한다() {
// given
String wrongPassword = "wrongPassword";
PasswordUpdateRequest request = new PasswordUpdateRequest(wrongPassword, newPassword, newPassword);
// when & then
assertThatThrownBy(() -> myPageService.updatePassword(user.getId(), request))
.isInstanceOf(CustomException.class)
.hasMessage(PASSWORD_MISMATCH.getMessage());
}
@ParameterizedTest
@EnumSource(value = AuthType.class, names = {"KAKAO", "APPLE"})
void 소셜_로그인_사용자가_비밀번호를_변경하면_예외가_발생한다(AuthType authType) {
// given
SiteUser oauthUser = siteUserFixtureBuilder.siteUser()
.email("oauth@example.com")
.authType(authType)
.nickname("소셜로그인사용자")
.profileImageUrl("profileImageUrl")
.role(Role.MENTEE)
.password("randomPassword")
.create();
PasswordUpdateRequest request = new PasswordUpdateRequest("anyPassword", "newPassword", "newPassword");
// when & then
assertThatThrownBy(() -> myPageService.updatePassword(oauthUser.getId(), request))
.isInstanceOf(CustomException.class)
.hasMessage(OAUTH_USER_CANNOT_CHANGE_PASSWORD.getMessage());
}
}
@Nested
class 관심_지역_및_국가_변경_테스트 {
private Country 미국;
private Country 캐나다;
private Country 일본;
private Region 영미권;
private Region 아시아;
@BeforeEach
void setUp() {
미국 = countryFixture.미국();
캐나다 = countryFixture.캐나다();
일본 = countryFixture.일본();
영미권 = regionFixture.영미권();
아시아 = regionFixture.아시아();
}
@Test
void 관심_지역과_국가를_성공적으로_수정한다() {
// given
interestedCountryRepository.save(new InterestedCountry(user, 미국));
interestedRegionRepository.save(new InterestedRegion(user, 영미권));
List<String> newCountries = List.of(캐나다.getKoreanName(), 일본.getKoreanName());
List<String> newRegions = List.of(아시아.getKoreanName());
LocationUpdateRequest request = new LocationUpdateRequest(newRegions, newCountries);
// when
myPageService.updateLocation(user.getId(), request);
// then
List<InterestedCountry> updatedCountries = interestedCountryRepository.findAllBySiteUserId(user.getId());
List<InterestedRegion> updatedRegions = interestedRegionRepository.findAllBySiteUserId(user.getId());
assertAll(
() -> assertThat(updatedCountries)
.extracting(InterestedCountry::getCountryCode)
.containsExactlyInAnyOrder(캐나다.getCode(), 일본.getCode()),
() -> assertThat(updatedRegions)
.extracting(InterestedRegion::getRegionCode)
.containsExactly(아시아.getCode())
);
}
@Test
void 기존에_관심_지역과_국가가_없어도_성공적으로_추가된다() {
// given
List<String> newCountries = List.of(미국.getKoreanName());
List<String> newRegions = List.of(영미권.getKoreanName());
LocationUpdateRequest request = new LocationUpdateRequest(newRegions, newCountries);
// when
myPageService.updateLocation(user.getId(), request);
// then
List<InterestedCountry> updatedCountries = interestedCountryRepository.findAllBySiteUserId(user.getId());
List<InterestedRegion> updatedRegions = interestedRegionRepository.findAllBySiteUserId(user.getId());
assertAll(
() -> assertThat(updatedCountries)
.extracting(InterestedCountry::getCountryCode)
.containsExactly(미국.getCode()),
() -> assertThat(updatedRegions)
.extracting(InterestedRegion::getRegionCode)
.containsExactly(영미권.getCode())
);
}
@Test
void 빈_리스트를_전달하면_모든_관심_지역과_국가가_삭제된다() {
// given
interestedCountryRepository.save(new InterestedCountry(user, 미국));
interestedRegionRepository.save(new InterestedRegion(user, 영미권));
LocationUpdateRequest request = new LocationUpdateRequest(List.of(), List.of());
// when
myPageService.updateLocation(user.getId(), request);
// then
List<InterestedCountry> updatedCountries = interestedCountryRepository.findAllBySiteUserId(user.getId());
List<InterestedRegion> updatedRegions = interestedRegionRepository.findAllBySiteUserId(user.getId());
assertAll(
() -> assertThat(updatedCountries).isEmpty(),
() -> assertThat(updatedRegions).isEmpty()
);
}
}
}