Skip to content

Commit 34a2ede

Browse files
authored
refactor: 리뷰 생성 및 컨트롤러 테스트 리팩토링 (#254)
* refactor(review): review 생성 리팩토링 * test(review): review 생성 리팩토링에 따른 테스트 * refactor(exception): 유효성 검사 실패시 해당 메세지 출력하도록 변경 * test(exception): 유효성 검사 실패시 해당 메세지 출력하도록 변경에 따른 테스트 * refactor(controller-test): ControllerTestSupport 리팩토링 - 컨트롤러 테스트시 print() 일괄 적용 - print()시 한글 깨짐 현상 해결 * test(controller-test): ControllerTestSupport 리팩토링에 따른 테스트 - 컨트롤러 테스트시 print() 일괄 적용 - print()시 한글 깨짐 현상 해결 * test(volunteer-apply): 누락된 테스트 추가 * test(controller-test): print() 제거
1 parent 82fbc68 commit 34a2ede

22 files changed

+341
-340
lines changed

src/main/java/com/somemore/domains/review/repository/ReviewRepositoryImpl.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ public class ReviewRepositoryImpl implements ReviewRepository {
2727
private final ReviewJpaRepository reviewJpaRepository;
2828
private final JPAQueryFactory queryFactory;
2929

30-
private final static QReview review = QReview.review;
31-
private final static QVolunteerApply volunteerApply = QVolunteerApply.volunteerApply;
32-
private final static QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard;
30+
private static final QReview review = QReview.review;
31+
private static final QVolunteerApply volunteerApply = QVolunteerApply.volunteerApply;
32+
private static final QRecruitBoard recruitBoard = QRecruitBoard.recruitBoard;
3333

3434
@Override
3535
public Review save(Review review) {
@@ -55,31 +55,31 @@ public boolean existsByVolunteerApplyId(Long volunteerApplyId) {
5555
public Page<Review> findAllByVolunteerIdAndSearch(UUID volunteerId,
5656
ReviewSearchCondition condition) {
5757

58-
BooleanExpression predicate = review.volunteerId.eq(volunteerId)
59-
.and(eqVolunteerCategory(condition.category()))
58+
BooleanExpression exp = volunteerIdEq(volunteerId)
59+
.and(volunteerCategoryEq(condition.category()))
6060
.and(isNotDeleted());
6161

62-
return getReviews(condition, predicate);
62+
return getReviews(condition, exp);
6363

6464
}
6565

6666
@Override
6767
public Page<Review> findAllByCenterIdAndSearch(UUID centerId, ReviewSearchCondition condition) {
6868

69-
BooleanExpression predicate = recruitBoard.centerId.eq(centerId)
70-
.and(eqVolunteerCategory(condition.category()))
69+
BooleanExpression exp = centerIdEq(centerId)
70+
.and(volunteerCategoryEq(condition.category()))
7171
.and(isNotDeleted());
7272

73-
return getReviews(condition, predicate);
73+
return getReviews(condition, exp);
7474
}
7575

7676
@NotNull
77-
private Page<Review> getReviews(ReviewSearchCondition condition, BooleanExpression predicate) {
77+
private Page<Review> getReviews(ReviewSearchCondition condition, BooleanExpression exp) {
7878
List<Review> content = queryFactory.select(review)
7979
.from(review)
8080
.join(volunteerApply).on(review.volunteerApplyId.eq(volunteerApply.id))
8181
.join(recruitBoard).on(recruitBoard.id.eq(volunteerApply.recruitBoardId))
82-
.where(predicate)
82+
.where(exp)
8383
.offset(condition.pageable().getOffset())
8484
.limit(condition.pageable().getPageSize())
8585
.orderBy(toOrderSpecifiers(condition.pageable().getSort()))
@@ -90,16 +90,24 @@ private Page<Review> getReviews(ReviewSearchCondition condition, BooleanExpressi
9090
.from(review)
9191
.join(volunteerApply).on(review.volunteerApplyId.eq(volunteerApply.id))
9292
.join(recruitBoard).on(recruitBoard.id.eq(volunteerApply.recruitBoardId))
93-
.where(predicate);
93+
.where(exp);
9494

9595
return PageableExecutionUtils.getPage(content, condition.pageable(), countQuery::fetchOne);
9696
}
9797

98+
private static BooleanExpression volunteerIdEq(UUID volunteerId) {
99+
return review.volunteerId.eq(volunteerId);
100+
}
101+
102+
private static BooleanExpression centerIdEq(UUID centerId) {
103+
return recruitBoard.centerId.eq(centerId);
104+
}
105+
98106
private BooleanExpression isNotDeleted() {
99107
return review.deleted.isFalse();
100108
}
101109

102-
private BooleanExpression eqVolunteerCategory(VolunteerCategory category) {
110+
private BooleanExpression volunteerCategoryEq(VolunteerCategory category) {
103111
return category != null
104112
? recruitBoard.recruitmentInfo.volunteerCategory.eq(category) : null;
105113
}

src/main/java/com/somemore/domains/review/service/CreateReviewService.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import com.somemore.domains.review.dto.request.ReviewCreateRequestDto;
1212
import com.somemore.domains.review.usecase.CreateReviewUseCase;
1313

14+
import com.somemore.global.exception.DuplicateException;
1415
import java.util.UUID;
1516
import lombok.RequiredArgsConstructor;
1617
import org.springframework.stereotype.Service;
@@ -27,7 +28,7 @@ public class CreateReviewService implements CreateReviewUseCase {
2728
@Override
2829
public Long createReview(ReviewCreateRequestDto requestDto, UUID volunteerId, String imgUrl) {
2930
VolunteerApply apply = getVolunteerApply(requestDto.recruitBoardId(), volunteerId);
30-
validateReviewNotExist(apply);
31+
validateDuplicateReview(apply);
3132
validateActivityCompletion(apply);
3233

3334
Review review = requestDto.toEntity(apply, volunteerId, imgUrl);
@@ -38,16 +39,16 @@ private VolunteerApply getVolunteerApply(Long recruitBoardId, UUID volunteerId)
3839
return volunteerApplyQueryUseCase.getByRecruitIdAndVolunteerId(recruitBoardId, volunteerId);
3940
}
4041

41-
private void validateReviewNotExist(VolunteerApply apply) {
42+
private void validateDuplicateReview(VolunteerApply apply) {
4243
if (reviewRepository.existsByVolunteerApplyId(apply.getId())) {
43-
throw new BadRequestException(REVIEW_ALREADY_EXISTS.getMessage());
44+
throw new DuplicateException(REVIEW_ALREADY_EXISTS);
4445
}
4546
}
4647

4748
private void validateActivityCompletion(VolunteerApply apply) {
4849
if (apply.isVolunteerActivityCompleted()) {
4950
return;
5051
}
51-
throw new BadRequestException(REVIEW_RESTRICTED_TO_ATTENDED.getMessage());
52+
throw new BadRequestException(REVIEW_RESTRICTED_TO_ATTENDED);
5253
}
5354
}

src/main/java/com/somemore/domains/volunteerapply/service/VolunteerApplyQueryService.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88
import com.somemore.domains.volunteerapply.dto.response.VolunteerApplySummaryResponseDto;
99
import com.somemore.domains.volunteerapply.repository.VolunteerApplyRepository;
1010
import com.somemore.domains.volunteerapply.usecase.VolunteerApplyQueryUseCase;
11-
import com.somemore.global.exception.BadRequestException;
12-
11+
import com.somemore.global.exception.NoSuchElementException;
1312
import java.util.List;
1413
import java.util.UUID;
1514
import lombok.RequiredArgsConstructor;
@@ -35,7 +34,7 @@ public List<UUID> getVolunteerIdsByRecruitIds(List<Long> recruitIds) {
3534
public VolunteerApply getByRecruitIdAndVolunteerId(Long recruitId, UUID volunteerId) {
3635
return volunteerApplyRepository.findByRecruitIdAndVolunteerId(recruitId, volunteerId)
3736
.orElseThrow(
38-
() -> new BadRequestException(NOT_EXISTS_VOLUNTEER_APPLY));
37+
() -> new NoSuchElementException(NOT_EXISTS_VOLUNTEER_APPLY));
3938
}
4039

4140
@Override
@@ -49,7 +48,7 @@ public VolunteerApplySummaryResponseDto getSummaryByRecruitId(Long recruitId) {
4948

5049
@Override
5150
public VolunteerApplyResponseDto getVolunteerApplyByRecruitIdAndVolunteerId(Long recruitId,
52-
UUID volunteerId) {
51+
UUID volunteerId) {
5352
VolunteerApply apply = getByRecruitIdAndVolunteerId(recruitId, volunteerId);
5453

5554
return VolunteerApplyResponseDto.from(apply);

src/main/java/com/somemore/global/exception/DuplicateException.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
public class DuplicateException extends RuntimeException{
44

5+
public DuplicateException(final ExceptionMessage message) {
6+
super(message.getMessage());
7+
}
58
public DuplicateException(final String message) {
69
super(message);
710
}

src/main/java/com/somemore/global/exception/handler/GlobalExceptionHandler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ ProblemDetail handleDuplicateException(final DuplicateException e) {
4949
@ExceptionHandler(MethodArgumentNotValidException.class)
5050
ProblemDetail handleMethodArgumentNotValid(final MethodArgumentNotValidException e) {
5151

52-
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, e.getMessage());
52+
String errorMessage = e.getBindingResult().getAllErrors().getFirst().getDefaultMessage();
53+
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.BAD_REQUEST, errorMessage);
5354

5455
problemDetail.setTitle("유효성 예외");
55-
problemDetail.setDetail("입력 데이터 유효성 검사가 실패했습니다. 각 필드를 확인해주세요.");
5656

5757
return problemDetail;
5858
}

src/test/java/com/somemore/domains/center/controller/CenterProfileCommandApiControllerTest.java

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,31 @@
11
package com.somemore.domains.center.controller;
22

3-
import com.fasterxml.jackson.databind.ObjectMapper;
3+
import static org.mockito.ArgumentMatchers.any;
4+
import static org.mockito.ArgumentMatchers.anyString;
5+
import static org.mockito.BDDMockito.given;
6+
import static org.mockito.BDDMockito.willDoNothing;
7+
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
8+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
9+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
10+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
11+
412
import com.somemore.domains.center.dto.request.CenterProfileUpdateRequestDto;
513
import com.somemore.domains.center.usecase.command.UpdateCenterProfileUseCase;
614
import com.somemore.global.imageupload.usecase.ImageUploadUseCase;
715
import com.somemore.support.ControllerTestSupport;
816
import com.somemore.support.annotation.WithMockCustomUser;
17+
import java.util.UUID;
918
import org.junit.jupiter.api.DisplayName;
1019
import org.junit.jupiter.api.Test;
11-
import org.springframework.beans.factory.annotation.Autowired;
1220
import org.springframework.boot.test.mock.mockito.MockBean;
1321
import org.springframework.http.MediaType;
1422
import org.springframework.mock.web.MockHttpServletRequest;
1523
import org.springframework.mock.web.MockMultipartFile;
16-
import org.springframework.test.web.servlet.MockMvc;
1724
import org.springframework.test.web.servlet.request.MockMultipartHttpServletRequestBuilder;
1825
import org.springframework.test.web.servlet.request.RequestPostProcessor;
1926

20-
import java.util.UUID;
21-
22-
import static org.mockito.ArgumentMatchers.any;
23-
import static org.mockito.ArgumentMatchers.anyString;
24-
import static org.mockito.BDDMockito.given;
25-
import static org.mockito.BDDMockito.willDoNothing;
26-
import static org.springframework.http.MediaType.MULTIPART_FORM_DATA;
27-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
28-
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
29-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
30-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
31-
3227
class CenterProfileCommandApiControllerTest extends ControllerTestSupport {
3328

34-
@Autowired
35-
private MockMvc mockMvc;
36-
37-
@Autowired
38-
private ObjectMapper objectMapper;
39-
4029
@MockBean
4130
private UpdateCenterProfileUseCase updateCenterProfileUseCase;
4231

@@ -92,7 +81,6 @@ public MockHttpServletRequest postProcessRequest(MockHttpServletRequest request)
9281
.header("Authorization", "Bearer access-token"))
9382

9483
//then
95-
.andDo(print())
9684
.andExpect(status().isOk())
9785
.andExpect(jsonPath("$.code").value(200))
9886
.andExpect(jsonPath("$.data").isEmpty())

src/test/java/com/somemore/domains/center/controller/CenterQueryApiControllerTest.java

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,25 @@
11
package com.somemore.domains.center.controller;
22

3+
import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_CENTER;
4+
import static org.mockito.Mockito.times;
5+
import static org.mockito.Mockito.verify;
6+
import static org.mockito.Mockito.when;
7+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
8+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
9+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
10+
311
import com.somemore.domains.center.dto.response.CenterProfileResponseDto;
412
import com.somemore.domains.center.usecase.query.CenterQueryUseCase;
513
import com.somemore.global.exception.BadRequestException;
614
import com.somemore.support.ControllerTestSupport;
15+
import java.util.List;
16+
import java.util.UUID;
717
import org.junit.jupiter.api.BeforeEach;
818
import org.junit.jupiter.api.DisplayName;
919
import org.junit.jupiter.api.Test;
1020
import org.springframework.boot.test.mock.mockito.MockBean;
1121
import org.springframework.http.MediaType;
1222

13-
import java.util.List;
14-
import java.util.UUID;
15-
16-
import static com.somemore.global.exception.ExceptionMessage.NOT_EXISTS_CENTER;
17-
import static org.mockito.Mockito.*;
18-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
19-
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
20-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
21-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
22-
2323
class CenterQueryApiControllerTest extends ControllerTestSupport {
2424

2525
@MockBean
@@ -53,16 +53,18 @@ void getCenterProfile() throws Exception {
5353
get("/api/center/profile/{centerId}", centerId)
5454
.contentType(MediaType.APPLICATION_JSON)
5555
)
56-
.andDo(print())
5756
.andExpect(status().isOk())
5857
.andExpect(jsonPath("$.code").value("200"))
5958
.andExpect(jsonPath("$.message").value("기관 프로필 조회 성공"))
6059
.andExpect(jsonPath("$.data.center_id").value(centerId.toString())) // center_id로 수정
6160
.andExpect(jsonPath("$.data.name").value("Test Center"))
62-
.andExpect(jsonPath("$.data.contact_number").value("010-1234-5678")) // contact_number로 수정
63-
.andExpect(jsonPath("$.data.img_url").value("http://example.com/image.jpg")) // img_url로 수정
61+
.andExpect(jsonPath("$.data.contact_number").value(
62+
"010-1234-5678")) // contact_number로 수정
63+
.andExpect(jsonPath("$.data.img_url").value(
64+
"http://example.com/image.jpg")) // img_url로 수정
6465
.andExpect(jsonPath("$.data.introduce").value("This is a test center."))
65-
.andExpect(jsonPath("$.data.homepage_link").value("http://example.com")) // homepage_link로 수정
66+
.andExpect(jsonPath("$.data.homepage_link").value(
67+
"http://example.com")) // homepage_link로 수정
6668
.andExpect(jsonPath("$.data.prefer_items").isArray()); // prefer_items로 수정
6769

6870
verify(centerQueryUseCase, times(1)).getCenterProfileByCenterId(centerId);
@@ -81,7 +83,6 @@ void getCenterProfile_NotFound() throws Exception {
8183
get("/api/center/profile/{centerId}", nonExistentCenterId)
8284
.contentType(MediaType.APPLICATION_JSON)
8385
)
84-
.andDo(print())
8586
.andExpect(status().isBadRequest())
8687
.andExpect(jsonPath("$.status").value("400"))
8788
.andExpect(jsonPath("$.detail").value("존재하지 않는 기관입니다."));

src/test/java/com/somemore/domains/center/controller/PreferItemCommandApiControllerTest.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,26 @@
11
package com.somemore.domains.center.controller;
22

3+
import static org.mockito.BDDMockito.given;
4+
import static org.mockito.Mockito.doThrow;
5+
import static org.mockito.Mockito.verify;
6+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
7+
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
8+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
9+
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
10+
311
import com.somemore.domains.center.dto.request.PreferItemCreateRequestDto;
412
import com.somemore.domains.center.dto.response.PreferItemCreateResponseDto;
513
import com.somemore.domains.center.usecase.command.CreatePreferItemUseCase;
614
import com.somemore.domains.center.usecase.command.DeletePreferItemUseCase;
715
import com.somemore.global.exception.BadRequestException;
816
import com.somemore.support.ControllerTestSupport;
917
import com.somemore.support.annotation.WithMockCustomUser;
18+
import java.util.UUID;
1019
import org.junit.jupiter.api.DisplayName;
1120
import org.junit.jupiter.api.Test;
1221
import org.springframework.boot.test.mock.mockito.MockBean;
1322
import org.springframework.http.MediaType;
1423

15-
import java.util.UUID;
16-
17-
import static org.mockito.BDDMockito.given;
18-
import static org.mockito.Mockito.doThrow;
19-
import static org.mockito.Mockito.verify;
20-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
21-
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
22-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
23-
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
24-
2524
class PreferItemCommandApiControllerTest extends ControllerTestSupport {
2625

2726
@MockBean

0 commit comments

Comments
 (0)