From d6c95fc9eae3d56b87273ed4c0f6d3e63a69d036 Mon Sep 17 00:00:00 2001 From: dfdrdodm95 Date: Wed, 1 May 2024 14:57:00 +0900 Subject: [PATCH 1/9] =?UTF-8?q?Exception=20=EA=B4=80=EB=A0=A8=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/error/ReviewErrorCode.java | 16 +++ .../review/exception/ReviewException.java | 14 ++ .../exception/ReviewExceptionHandler.java | 35 +++++ .../review/service/ReviewServiceTest.java | 133 +++++++++--------- 4 files changed, 130 insertions(+), 68 deletions(-) create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/error/ReviewErrorCode.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/error/ReviewErrorCode.java b/src/main/java/com/kidsqueue/kidsqueue/review/error/ReviewErrorCode.java new file mode 100644 index 0000000..b690c33 --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/error/ReviewErrorCode.java @@ -0,0 +1,16 @@ +package com.kidsqueue.kidsqueue.review.error; + +import com.kidsqueue.kidsqueue.common.error.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@AllArgsConstructor +@Getter +public enum ReviewErrorCode implements ErrorCode { + Hospital_Not_Found(HttpStatus.NOT_FOUND, ""), + Parent_Not_Found(HttpStatus.NOT_FOUND, ""); + + private final HttpStatus httpStatusCode; + private final String description; +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java new file mode 100644 index 0000000..51ad145 --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java @@ -0,0 +1,14 @@ +package com.kidsqueue.kidsqueue.review.exception; + +import com.kidsqueue.kidsqueue.common.error.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +@AllArgsConstructor +public class ReviewException extends RuntimeException { + private final ErrorCode errorCode; + private final String description; +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java new file mode 100644 index 0000000..c67314b --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java @@ -0,0 +1,35 @@ +package com.kidsqueue.kidsqueue.review.exception; + +import com.kidsqueue.kidsqueue.common.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@Slf4j +@RestControllerAdvice +public class ReviewExceptionHandler { + @ExceptionHandler(value = ReviewException.class) + public ResponseEntity reviewExceptionHandler(ReviewException reviewException) { + log.error("", reviewException); + + return ResponseEntity + .status(reviewException.getErrorCode().getHttpStatusCode()) + .body(Api.error(reviewException.getDescription())); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidException ex) { + log.error("", ex); + + String errorMessage = "Validation failed"; + + return ResponseEntity + .status(HttpStatus.BAD_REQUEST) + .body(Api.error(errorMessage)); + } +} + + diff --git a/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java b/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java index 1dda71e..f3f4c76 100644 --- a/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java +++ b/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java @@ -39,73 +39,14 @@ class ReviewServiceTest { @BeforeEach void setUp() { - // TODO : 이 코드를 축약할 방법은 없는지 생각 중 - Hospital hospital1 = Hospital.builder() - .name("병원1") - .address("주소1") - .description("설명1") - .phoneNumber("번호1") - .maxNumOfPeople(5) - .status(Status.OPEN) - .build(); - - Hospital hospital2 = Hospital.builder() - .name("병원2") - .address("주소2") - .description("설명2") - .phoneNumber("번호2") - .maxNumOfPeople(5) - .status(Status.OPEN) - .build(); - - hospitalRepository.save(hospital1); - hospitalRepository.save(hospital2); - - Parent parent1 = Parent.builder() - .loginId("아이디1") - .password("비밀번호1") - .nickname("별명1") - .name("이름1") - .age("20") - .gender(남) - .phoneNumber("번호1") - .residentRegistrationNumber("3333334444444") - .email("test1@test.com") - .role(USER) - .build(); - - Parent parent2 = Parent.builder() - .loginId("아이디2") - .password("비밀번호2") - .nickname("별명2") - .name("이름2") - .age("20") - .gender(여) - .phoneNumber("번호2") - .residentRegistrationNumber("5555556666666") - .email("test2@test.com") - .role(USER) - .build(); - parentRepository.save(parent1); - parentRepository.save(parent2); + Hospital hospital1 = generateHospital("병원1", "000-0000-0001"); + Hospital hospital2 = generateHospital("병원2", "000-0000-0002"); - Review review1 = Review.builder() - .title("리뷰1") - .score(5) - .description("설명1") - .hospital(hospital1) - .parent(parent1) - .build(); + Parent parent1 = generateParent("testSignUp1", "010-0000-0001", "0000000000000", "testSignUp@naver.com"); + Parent parent2 = generateParent("testSignUp2", "010-0000-0002", "0000000000001", "testSignUp2@naver.com"); - Review review2 = Review.builder() - .title("리뷰2") - .score(5) - .description("설명2") - .hospital(hospital1) - .parent(parent1) - .build(); - reviewRepository.save(review1); - reviewRepository.save(review2); + generateReview("리뷰1", hospital1, parent1); + generateReview("리뷰2", hospital2, parent2); } @Test @@ -128,14 +69,28 @@ void findAllDesc() { assertTrue((list.get(0).getCreatedBy().isAfter(list.get(1).getCreatedBy()))); } + @Test - void findReviewById() { - // TODO : ID 리터럴을 어떻게 구해야 맞을까? + @DisplayName("리뷰 생성에 실패한다. - hospital id 조회 실패") + void createReview_negativeCase_notFound_hospitalId() { + } + + + @Test + @DisplayName("리뷰 생성에 실패한다. - parent id 조회 실패") + void createReview_negativeCase_notFound_parentId() { + + } + + @Test + @DisplayName("리뷰 생성에 실패한다. - id 조회 모두 실패") + void createReview_negativeCase_notFound_hospitalId_and_parentId() { + } @Test @DisplayName("리뷰 생성에 성공한다.") - void createReview() { + void createReview_positiveCase() { // TODO : given 이 너무 무겁지만 API 스펙을 변경하지 않는 선에서 auto increment 되는 ID를 어떻게 특정할지 모르겠음 int prevSize = reviewRepository.findAll().size(); Long hospitalId = hospitalRepository.findAll().get(0).getId(); @@ -184,4 +139,46 @@ void deleteReview() { assertEquals(0, reviewRepository.findById(id).get().getIsActive()); else fail("deleteReview 메서드는 삭제되는 대신 isActive 가 변경돼야 합니다."); } + + Hospital generateHospital(String name, String phoneNumber) { + Hospital hospital = Hospital.builder() + .name(name) + .address(name + "주소") + .description(name + "설명") + .phoneNumber(phoneNumber) + .maxNumOfPeople(5) + .status(Status.OPEN) + .build(); + hospitalRepository.save(hospital); + + return hospital; + } + + Parent generateParent(String loginId, String phoneNumber, String residentRegistrationNumber, String email) { + Parent parent = Parent.builder() + .loginId(loginId) + .password("비밀번호") + .nickname("별명") + .name("이름") + .age("20") + .gender(남) + .phoneNumber(phoneNumber) + .residentRegistrationNumber(residentRegistrationNumber) + .email(email) + .role(USER) + .build(); + parentRepository.save(parent); + return parent; + } + + void generateReview(String title, Hospital hospital, Parent parent) { + Review review = Review.builder() + .title(title) + .score(5) + .description(title + "설명") + .hospital(hospital) + .parent(parent) + .build(); + reviewRepository.save(review); + } } \ No newline at end of file From 6ac2fbb3c7312b35a20d972f1ceec0491118cd6a Mon Sep 17 00:00:00 2001 From: dfdrdodm95 Date: Sun, 5 May 2024 20:03:14 +0900 Subject: [PATCH 2/9] =?UTF-8?q?exception=20=EC=BD=94=EB=93=9C=20=EB=B0=98?= =?UTF-8?q?=EC=98=81=EA=B3=BC=20=EA=B4=80=EB=A0=A8=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=20=20=20=20*=20API=20=EC=8A=A4=ED=8E=99?= =?UTF-8?q?=20=EC=9C=A0=EC=A7=80=EB=A5=BC=20=EC=9C=84=ED=95=98=EC=97=AC=20?= =?UTF-8?q?exception=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=20=20=20=20=20=20=20=20*=20exception=20?= =?UTF-8?q?=EB=B0=9C=EC=83=9D=20=EC=8B=9C=20data=20=EC=A0=84=EB=8B=AC?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20Json=20Mapper=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=20=20=20=20=20=20=20=20=20=20=20=20*=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=EC=9D=84=20=EC=9C=84=ED=95=9C=20DTO=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EB=B3=80=EA=B2=BD=20=20=20=20=20*=20excep?= =?UTF-8?q?tion=20handler=20=ED=81=B4=EB=9E=98=EC=8A=A4=EB=93=A4=EC=9D=B4?= =?UTF-8?q?=20=EB=B3=B5=EC=88=98=20=EA=B0=9C=20=EC=A1=B4=EC=9E=AC=ED=95=98?= =?UTF-8?q?=EC=97=AC=20=ED=95=84=EC=9A=94=EC=82=AC=ED=95=AD=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=20=20=20=20=20=20=20=20*=20Priority=EC=99=80=20bas?= =?UTF-8?q?ePackages=20=EC=84=A4=EC=A0=95=20=20=20=20=20*=20=EC=84=9C?= =?UTF-8?q?=EB=B9=84=EC=8A=A4=20=EC=BD=94=EB=93=9C=20exception=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kidsqueue/kidsqueue/common/Api.java | 1 + .../kidsqueue/common/forTest/initDb.java | 87 ++++++++++++++ .../kidsqueue/common/util/MyObjectMapper.java | 20 ++++ .../review/controller/ReviewController.java | 51 ++++---- .../kidsqueue/review/db/ReviewRepository.java | 5 +- .../review/dtos/ReviewCreateDto.java | 2 +- .../kidsqueue/review/dtos/ReviewDto.java | 31 ++--- .../kidsqueue/review/dtos/ReviewReadDto.java | 29 +++++ .../review/dtos/ReviewUpdateDto.java | 2 +- .../{error => exception}/ReviewErrorCode.java | 8 +- .../review/exception/ReviewException.java | 38 +++++- .../exception/ReviewExceptionHandler.java | 20 +++- .../review/service/ReviewConverter.java | 14 +-- .../review/service/ReviewService.java | 110 +++++++----------- .../review/service/ReviewServiceTest.java | 24 ++-- 15 files changed, 291 insertions(+), 151 deletions(-) create mode 100644 src/main/java/com/kidsqueue/kidsqueue/common/forTest/initDb.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java rename src/main/java/com/kidsqueue/kidsqueue/review/{error => exception}/ReviewErrorCode.java (56%) diff --git a/src/main/java/com/kidsqueue/kidsqueue/common/Api.java b/src/main/java/com/kidsqueue/kidsqueue/common/Api.java index 1303ecc..9423f70 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/common/Api.java +++ b/src/main/java/com/kidsqueue/kidsqueue/common/Api.java @@ -1,5 +1,6 @@ package com.kidsqueue.kidsqueue.common; +import com.fasterxml.jackson.annotation.JsonInclude; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/src/main/java/com/kidsqueue/kidsqueue/common/forTest/initDb.java b/src/main/java/com/kidsqueue/kidsqueue/common/forTest/initDb.java new file mode 100644 index 0000000..2261510 --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/common/forTest/initDb.java @@ -0,0 +1,87 @@ +package com.kidsqueue.kidsqueue.common.forTest; + +import com.kidsqueue.kidsqueue.hospital.db.Hospital; +import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; +import com.kidsqueue.kidsqueue.hospital.db.enums.Status; +import com.kidsqueue.kidsqueue.parent.db.Parent; +import com.kidsqueue.kidsqueue.parent.db.ParentRepository; +import com.kidsqueue.kidsqueue.review.db.ReviewRepository; +import com.kidsqueue.kidsqueue.review.model.Review; +import jakarta.annotation.PostConstruct; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; +import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; + +@Service +@RequiredArgsConstructor +public class initDb { + + /** + * test 용도로 DB에 초기 데이터를 넣어주는 클래스 + */ + + @Autowired private final HospitalRepository hospitalRepository; + @Autowired private final ParentRepository parentRepository; + @Autowired private final ReviewRepository reviewRepository; + @PostConstruct + void init() { + setUp(); + } + + + void setUp() { + Hospital hospital1 = generateHospital("병원1", "000-0000-0001"); + Hospital hospital2 = generateHospital("병원2", "000-0000-0002"); + + Parent parent1 = generateParent("testSignUp1", "010-0000-0001", "0000000000000", "testSignUp@naver.com"); + Parent parent2 = generateParent("testSignUp2", "010-0000-0002", "0000000000001", "testSignUp2@naver.com"); + + generateReview("리뷰1", hospital1, parent1); + generateReview("리뷰2", hospital2, parent2); + } + + Hospital generateHospital(String name, String phoneNumber) { + Hospital hospital = Hospital.builder() + .name(name) + .address(name + "주소") + .description(name + "설명") + .phoneNumber(phoneNumber) + .maxNumOfPeople(5) + .status(Status.OPEN) + .build(); + hospitalRepository.save(hospital); + + return hospital; + } + + Parent generateParent(String loginId, String phoneNumber, String residentRegistrationNumber, String email) { + Parent parent = Parent.builder() + .loginId(loginId) + .password("비밀번호") + .nickname(loginId + "별명") + .name("이름") + .age("20") + .gender(남) + .phoneNumber(phoneNumber) + .residentRegistrationNumber(residentRegistrationNumber) + .email(email) + .role(USER) + .build(); + parentRepository.save(parent); + return parent; + } + + void generateReview(String title, Hospital hospital, Parent parent) { + Review review = Review.builder() + .title(title) + .score(5) + .description(title + "설명") + .hospital(hospital) + .parent(parent) + .build(); + reviewRepository.save(review); + } +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java b/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java new file mode 100644 index 0000000..4e4e756 --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java @@ -0,0 +1,20 @@ +package com.kidsqueue.kidsqueue.common.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class MyObjectMapper { + private static ObjectMapper objectMapper; + + private MyObjectMapper() {} + public static String convertToJson(Object obj) throws JsonProcessingException { + return objectMapper.writeValueAsString(obj); + } + + public static ObjectMapper getInstance() { + if (objectMapper == null) { + objectMapper = new ObjectMapper(); + } + return objectMapper; + } +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java b/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java index c9a3281..9e62fa5 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java @@ -1,25 +1,22 @@ package com.kidsqueue.kidsqueue.review.controller; import com.kidsqueue.kidsqueue.common.Api; +import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; +import com.kidsqueue.kidsqueue.parent.db.ParentRepository; +import com.kidsqueue.kidsqueue.review.db.ReviewRepository; import com.kidsqueue.kidsqueue.review.dtos.ReviewCreateDto; -import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; +import com.kidsqueue.kidsqueue.review.dtos.ReviewReadDto; import com.kidsqueue.kidsqueue.review.dtos.ReviewUpdateDto; import com.kidsqueue.kidsqueue.review.service.ReviewService; -import java.util.List; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PatchMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @RestController @RequestMapping("/api/review") @@ -28,15 +25,22 @@ public class ReviewController { private final ReviewService reviewService; - public Api> get( + @Autowired final ReviewRepository reviewRepository; + @Autowired final private HospitalRepository hospitalRepository; + @Autowired final private ParentRepository parentRepository; + + // TODO : 반환 값을 바꿔볼까 고민 중 + + // TODO : 동작 안 함 /api/review?sortCondition=desc로 url 입력한 결과. + // 디버깅 필요함 + @GetMapping + public Api> get( @PageableDefault(page = 0, size = 10) Pageable pageable, - @RequestParam(required = false) String sortCondition, - @RequestParam(required = false) String name + @RequestParam(required = false) String sortCondition ) { System.out.println("sortCondition = " + sortCondition); - System.out.println("name = " + name); - Api> apiResponse; + Api> apiResponse; if ("desc".equals(sortCondition)) { apiResponse = reviewService.findAllDesc(pageable); @@ -50,9 +54,9 @@ public Api> get( return apiResponse; } - @GetMapping("/{id}") - public ResponseEntity> getReviewById(@PathVariable Long id) { - Api apiResponse = reviewService.findReviewById(id); + @GetMapping("/{review_id}") + public ResponseEntity> getReviewById(@PathVariable("review_id") Long id) { + Api apiResponse = reviewService.findReviewById(id); if (apiResponse.getData() != null) { apiResponse.setStatus(Api.SUCCESS_STATUS); @@ -80,8 +84,8 @@ public ResponseEntity> createReview(@RequestBody ReviewCrea } } - @PatchMapping("/{id}") - public ResponseEntity> updateReview(@PathVariable Long id, + @PatchMapping("/{review_id}") + public ResponseEntity> updateReview(@PathVariable("review_id") Long id, @RequestBody ReviewUpdateDto updateDto) { Api apiResponse = reviewService.updateReview(id, updateDto); @@ -96,8 +100,8 @@ public ResponseEntity> updateReview(@PathVariable Long id, } } - @DeleteMapping("/{id}") - public ResponseEntity> deleteReview(@PathVariable Long id) { + @DeleteMapping("/{review_id}") + public ResponseEntity> deleteReview(@PathVariable("review_id") Long id) { Api apiResponse = reviewService.deleteReview(id); if (apiResponse.getData() == null) { @@ -110,4 +114,5 @@ public ResponseEntity> deleteReview(@PathVariable Long id) { return new ResponseEntity<>(apiResponse, HttpStatus.BAD_REQUEST); } } + } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/db/ReviewRepository.java b/src/main/java/com/kidsqueue/kidsqueue/review/db/ReviewRepository.java index 350c28c..fa49bc6 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/db/ReviewRepository.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/db/ReviewRepository.java @@ -1,13 +1,12 @@ package com.kidsqueue.kidsqueue.review.db; -import com.kidsqueue.kidsqueue.hospital.db.Hospital; import com.kidsqueue.kidsqueue.review.model.Review; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; -import java.util.List; +import java.util.Optional; public interface ReviewRepository extends JpaRepository { // TODO : localDateTime으로 내림차순 정렬이 안 되어서 auto increment 되는 아이디를 기준으로 정렬했음 @@ -16,6 +15,8 @@ public interface ReviewRepository extends JpaRepository { Page findAllByIsActiveOrderByIdAsc(Integer isActive, Pageable pageable); + Optional findByIdAndIsActive(Long id, Integer isActive); + @Query("select r from Review r " + " join fetch r.hospital") diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java index de5f29e..b629c9e 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java @@ -9,7 +9,7 @@ @Getter @Builder -public class ReviewCreateDto { +public class ReviewCreateDto implements ReviewDto { @NotBlank private String title; @NotBlank diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java index 907f798..96b0be4 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java @@ -1,28 +1,15 @@ package com.kidsqueue.kidsqueue.review.dtos; -import com.kidsqueue.kidsqueue.review.model.Review; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; +import com.fasterxml.jackson.core.JsonProcessingException; -import java.time.LocalDateTime; +import static com.kidsqueue.kidsqueue.common.util.MyObjectMapper.convertToJson; -@Getter -@NoArgsConstructor -@AllArgsConstructor -@SuperBuilder -public class ReviewDto { - private String title; - private Integer score; - private String description; - private LocalDateTime createdBy; - public Review toEntity() { - return Review.builder() - .title(title) - .score(score) - .description(description) - .createdBy(createdBy) - .build(); +public interface ReviewDto { + default String toJson() { + try { + return convertToJson(this); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java new file mode 100644 index 0000000..be00a7b --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java @@ -0,0 +1,29 @@ +package com.kidsqueue.kidsqueue.review.dtos; + +import com.kidsqueue.kidsqueue.review.model.Review; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.experimental.SuperBuilder; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@SuperBuilder +public class ReviewReadDto implements ReviewDto { + private String title; + private Integer score; + private String description; + private LocalDateTime createdBy; + public Review toEntity() { + return Review.builder() + .title(title) + .score(score) + .description(description) + .createdBy(createdBy) + .build(); + } + +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java index c6f7413..b0e59ff 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java @@ -7,7 +7,7 @@ @Getter @Builder -public class ReviewUpdateDto { +public class ReviewUpdateDto implements ReviewDto { @NotBlank private String title; @NotBlank diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/error/ReviewErrorCode.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewErrorCode.java similarity index 56% rename from src/main/java/com/kidsqueue/kidsqueue/review/error/ReviewErrorCode.java rename to src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewErrorCode.java index b690c33..1621a57 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/error/ReviewErrorCode.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewErrorCode.java @@ -1,4 +1,4 @@ -package com.kidsqueue.kidsqueue.review.error; +package com.kidsqueue.kidsqueue.review.exception; import com.kidsqueue.kidsqueue.common.error.ErrorCode; import lombok.AllArgsConstructor; @@ -8,8 +8,10 @@ @AllArgsConstructor @Getter public enum ReviewErrorCode implements ErrorCode { - Hospital_Not_Found(HttpStatus.NOT_FOUND, ""), - Parent_Not_Found(HttpStatus.NOT_FOUND, ""); + Review_Not_Found(HttpStatus.NOT_FOUND, "No Review"), + Hospital_Not_Found(HttpStatus.NOT_FOUND, "No Hospital"), + Parent_Not_Found(HttpStatus.NOT_FOUND, "No Parent"), + ; private final HttpStatus httpStatusCode; private final String description; diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java index 51ad145..11842b9 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java @@ -6,9 +6,43 @@ import lombok.RequiredArgsConstructor; @Getter -@RequiredArgsConstructor -@AllArgsConstructor public class ReviewException extends RuntimeException { private final ErrorCode errorCode; private final String description; + private final String jsonData; + + public ReviewException(ErrorCode errorCode) { + super(errorCode.getDescription()); + this.errorCode = errorCode; + this.description = errorCode.getDescription(); + this.jsonData = null; + } + + public ReviewException(ErrorCode errorCode, String description) { + super(description); + this.errorCode = errorCode; + this.description = description; + this.jsonData = null; + } + + public ReviewException(String jsonData, ErrorCode errorCode) { + super(errorCode.getDescription()); + this.errorCode = errorCode; + this.description = errorCode.getDescription(); + this.jsonData = jsonData; + } + + public ReviewException(String jsonData, ErrorCode errorCode, String description) { + super(description); + this.errorCode = errorCode; + this.description = description; + this.jsonData = jsonData; + } + + public ReviewException(ErrorCode errorCode, Throwable throwable) { + super(throwable); + this.errorCode = errorCode; + this.description = errorCode.getDescription(); + this.jsonData = null; + } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java index c67314b..3120185 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java @@ -1,6 +1,7 @@ package com.kidsqueue.kidsqueue.review.exception; import com.kidsqueue.kidsqueue.common.Api; +import jakarta.annotation.Priority; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -9,15 +10,20 @@ import org.springframework.web.bind.annotation.RestControllerAdvice; @Slf4j -@RestControllerAdvice +@Priority(0) +@RestControllerAdvice(basePackages = "com.kidsqueue.kidsqueue.review") public class ReviewExceptionHandler { + // TODO : ResponseEntity 형태로 반환하도록 다시 고칠 예정임 + // @ExceptionHandler(value = ReviewException.class) - public ResponseEntity reviewExceptionHandler(ReviewException reviewException) { + public Api reviewExceptionHandler(ReviewException reviewException) { log.error("", reviewException); - return ResponseEntity - .status(reviewException.getErrorCode().getHttpStatusCode()) - .body(Api.error(reviewException.getDescription())); + HttpStatus httpStatus = reviewException.getErrorCode().getHttpStatusCode(); + return Api.builder() + .status(getFullHttpStatus(httpStatus)) + .message(reviewException.getMessage()) + .build(); } @ExceptionHandler(MethodArgumentNotValidException.class) @@ -30,6 +36,10 @@ public ResponseEntity handleMethodArgumentNotValid(MethodArgumentNotValidEx .status(HttpStatus.BAD_REQUEST) .body(Api.error(errorMessage)); } + + String getFullHttpStatus(HttpStatus httpStatus) { + return httpStatus.value() + " " + httpStatus.getReasonPhrase(); + } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewConverter.java b/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewConverter.java index 83d32a0..0f2fed2 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewConverter.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewConverter.java @@ -1,13 +1,13 @@ package com.kidsqueue.kidsqueue.review.service; import com.kidsqueue.kidsqueue.review.model.Review; -import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; +import com.kidsqueue.kidsqueue.review.dtos.ReviewReadDto; import org.springframework.stereotype.Service; @Service public class ReviewConverter { - public ReviewDto toDto(Review review) { - return ReviewDto.builder() + public ReviewReadDto toDto(Review review) { + return ReviewReadDto.builder() .title(review.getTitle()) .score(review.getScore()) .description(review.getDescription()) @@ -15,11 +15,11 @@ public ReviewDto toDto(Review review) { .build(); } - public Review toEntity(ReviewDto reviewDto) { + public Review toEntity(ReviewReadDto reviewReadDto) { return Review.builder() - .title(reviewDto.getTitle()) - .description(reviewDto.getDescription()) - .score(reviewDto.getScore()) + .title(reviewReadDto.getTitle()) + .description(reviewReadDto.getDescription()) + .score(reviewReadDto.getScore()) .build(); } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java b/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java index 9a364d0..3b70008 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java @@ -6,9 +6,11 @@ import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; import com.kidsqueue.kidsqueue.parent.db.Parent; import com.kidsqueue.kidsqueue.parent.db.ParentRepository; +import com.kidsqueue.kidsqueue.review.exception.ReviewErrorCode; +import com.kidsqueue.kidsqueue.review.exception.ReviewException; import com.kidsqueue.kidsqueue.review.model.Review; import com.kidsqueue.kidsqueue.review.db.ReviewRepository; -import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; +import com.kidsqueue.kidsqueue.review.dtos.ReviewReadDto; import java.util.List; import java.util.Optional; @@ -19,6 +21,8 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import static com.kidsqueue.kidsqueue.review.exception.ReviewErrorCode.*; + @Service @RequiredArgsConstructor public class ReviewService { @@ -27,22 +31,22 @@ public class ReviewService { private final ParentRepository parentRepository; private final ReviewConverter reviewConverter; - public Api> findAllAsc(Pageable pageable) { + public Api> findAllAsc(Pageable pageable) { // Page 를 Page 로 변환 - Page reviewDtoPage = reviewRepository.findAllByIsActiveOrderByIdAsc(1, pageable) + Page reviewDtoPage = reviewRepository.findAllByIsActiveOrderByIdAsc(1, pageable) .map(reviewConverter::toDto); return getApiResponse(reviewDtoPage); } - public Api> findAllDesc(Pageable pageable) { - Page reviewDtoPage = reviewRepository.findAllByIsActiveOrderByIdDesc(1, pageable) + public Api> findAllDesc(Pageable pageable) { + Page reviewDtoPage = reviewRepository.findAllByIsActiveOrderByIdDesc(1, pageable) .map(reviewConverter::toDto); return getApiResponse(reviewDtoPage); } - private static Api> getApiResponse(Page reviewDtoPage) { - List reviewDtoList = reviewDtoPage.toList(); + private static Api> getApiResponse(Page reviewDtoPage) { + List reviewReadDtoList = reviewDtoPage.toList(); // Page 로 pagination 생성 Pagination pagination = Pagination.builder() @@ -54,104 +58,68 @@ private static Api> getApiResponse(Page reviewDtoPage .build(); // ApiResponse> 만들어서 리턴 - return Api.>builder() - .data(reviewDtoList) + return Api.>builder() + .data(reviewReadDtoList) .pagination(pagination) .build(); } - public Api findReviewById(Long id) { - Optional reviewOptional = reviewRepository.findById(id); + public Api findReviewById(Long id) { + Review review = reviewRepository.findByIdAndIsActive(id, 1) + .orElseThrow(() -> new ReviewException(Review_Not_Found)); - if (reviewOptional.isPresent()) { - ReviewDto reviewDto = reviewConverter.toDto(reviewOptional.get()); - return Api.builder() - .data(reviewDto) + ReviewReadDto reviewReadDto = reviewConverter.toDto(review); + return Api.builder() + .data(reviewReadDto) .status(Api.SUCCESS_STATUS) .message("리뷰 정보 조회 성공") .build(); - } else { - return Api.builder() - .status(Api.ERROR_STATUS) - .message("해당 리뷰를 찾을 수 없습니다.") - .build(); - } } + // TODO : 일치하지 않는 필드 일체를 전달하는 방법이 있으면 좋겠음 public Api createReview(ReviewCreateDto createDto) { - Optional optionalHospital = hospitalRepository.findById(createDto.getHospitalId()); - Optional optionalParent = parentRepository.findById(createDto.getParentId()); - if (optionalHospital.isEmpty() || optionalParent.isEmpty()) { - StringBuilder messageBuilder = new StringBuilder(); - if (optionalHospital.isEmpty()) { - messageBuilder.append("유효하지 않은 hospital_id : ").append(createDto.getHospitalId()).append("\n"); - } - if (optionalParent.isEmpty()) { - messageBuilder.append("유효하지 않은 parent_id : ").append(createDto.getParentId()); - } - - return Api.builder() - .status(Api.FAIL_STATUS) - .message(messageBuilder.toString()) - .build(); - } - - Hospital hospital = optionalHospital.get(); - Parent parent = optionalParent.get(); + Hospital hospital = hospitalRepository.findById(createDto.getHospitalId()) + .orElseThrow(() -> new ReviewException(createDto.toJson(), Hospital_Not_Found)); + Parent parent = parentRepository.findById(createDto.getParentId()) + .orElseThrow(() -> new ReviewException(createDto.toJson(), Parent_Not_Found)); Review review = createDto.toEntity(hospital, parent); reviewRepository.save(review); - return Api.builder() .data(createDto) .status(Api.SUCCESS_STATUS) .message("리뷰 정보 생성 성공") .build(); } + public Api updateReview(Long id, ReviewUpdateDto updateDto) { - Optional reviewOptional = reviewRepository.findById(id); + Review review = reviewRepository.findById(id) + .orElseThrow(() -> new ReviewException(updateDto.toJson(), Review_Not_Found)); - if (reviewOptional.isPresent()) { - // 엔티티 수정 - Review existingReview = reviewOptional.get(); - existingReview.setTitle(updateDto.getTitle()); - existingReview.setScore(updateDto.getScore()); - existingReview.setDescription(updateDto.getDescription()); + review.setTitle(updateDto.getTitle()); + review.setScore(updateDto.getScore()); + review.setDescription(updateDto.getDescription()); - Review updatedReview = reviewRepository.save(existingReview); + Review updatedReview = reviewRepository.save(review); - return Api.builder() + return Api.builder() .data(updateDto) .status(Api.SUCCESS_STATUS) .message("리뷰 정보 수정 성공") .build(); - } else { - return Api.builder() - .status(Api.ERROR_STATUS) - .message("해당 리뷰를 찾을 수 없습니다.") - .build(); - } } public Api deleteReview(Long id) { - Optional reviewOptional = reviewRepository.findById(id); + Review review = reviewRepository.findById(id) + .orElseThrow(() -> new ReviewException(Review_Not_Found)); - if (reviewOptional.isPresent()) { - Review existingReview = reviewOptional.get(); - existingReview.setIsActive(0); + review.setIsActive(0); + Review inactivatedReview = reviewRepository.save(review); - return Api.builder() + return Api.builder() .status(Api.SUCCESS_STATUS) .message("리뷰 정보 삭제 성공") - .data("리뷰 정보가 성공적으로 삭제되었습니다.") - .build(); - } else { - return Api.builder() - .status(Api.ERROR_STATUS) - .message("해당 리뷰를 찾을 수 없습니다.") + .data("리뷰 정보 삭제에 성공했습니다.") .build(); - } } - - -} +} \ No newline at end of file diff --git a/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java b/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java index f3f4c76..f44eabf 100644 --- a/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java +++ b/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java @@ -8,7 +8,7 @@ import com.kidsqueue.kidsqueue.parent.db.ParentRepository; import com.kidsqueue.kidsqueue.review.db.ReviewRepository; import com.kidsqueue.kidsqueue.review.dtos.ReviewCreateDto; -import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; +import com.kidsqueue.kidsqueue.review.dtos.ReviewReadDto; import com.kidsqueue.kidsqueue.review.dtos.ReviewUpdateDto; import com.kidsqueue.kidsqueue.review.model.Review; import jakarta.transaction.Transactional; @@ -23,7 +23,6 @@ import java.util.Optional; import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; -import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.여; import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; import static org.junit.jupiter.api.Assertions.*; @@ -37,6 +36,9 @@ class ReviewServiceTest { @Autowired ReviewRepository reviewRepository; + + // TODO : 리팩터링 반영되지 않은 코드, 참고 불가함 + @BeforeEach void setUp() { Hospital hospital1 = generateHospital("병원1", "000-0000-0001"); @@ -54,7 +56,7 @@ void setUp() { void findAllAsc() { PageRequest pageRequest = PageRequest.of(0, 10); - List list = reviewService.findAllAsc(pageRequest).getData(); + List list = reviewService.findAllAsc(pageRequest).getData(); assertTrue((list.get(0).getCreatedBy().isBefore(list.get(1).getCreatedBy()))); } @@ -64,12 +66,14 @@ void findAllAsc() { void findAllDesc() { PageRequest pageRequest = PageRequest.of(0, 10); - List list = reviewService.findAllDesc(pageRequest).getData(); + List list = reviewService.findAllDesc(pageRequest).getData(); assertTrue((list.get(0).getCreatedBy().isAfter(list.get(1).getCreatedBy()))); } + // TODO : given 조건으로 ID 리터럴을 준비하는 법, 아직 생각 못 했음 + @Test @DisplayName("리뷰 생성에 실패한다. - hospital id 조회 실패") void createReview_negativeCase_notFound_hospitalId() { @@ -82,12 +86,6 @@ void createReview_negativeCase_notFound_parentId() { } - @Test - @DisplayName("리뷰 생성에 실패한다. - id 조회 모두 실패") - void createReview_negativeCase_notFound_hospitalId_and_parentId() { - - } - @Test @DisplayName("리뷰 생성에 성공한다.") void createReview_positiveCase() { @@ -105,7 +103,6 @@ void createReview_positiveCase() { Api apiResponse = reviewService.createReview(reviewCreateDto); - // 검증문으로 2 가지를 보고 있는데 적절성 판단할 필요 있음 assertEquals("리뷰 정보 생성 성공", apiResponse.getMessage()); assertEquals(prevSize + 1, reviewRepository.findAll().size()); } @@ -133,10 +130,9 @@ void deleteReview() { reviewService.deleteReview(id); - // TODO : 더 나은 Optional 처리 방법이 없을까 고민 Optional reviewOptional = reviewRepository.findById(id); if (reviewOptional.isPresent()) - assertEquals(0, reviewRepository.findById(id).get().getIsActive()); + assertEquals(0, reviewOptional.get().getIsActive()); else fail("deleteReview 메서드는 삭제되는 대신 isActive 가 변경돼야 합니다."); } @@ -158,7 +154,7 @@ Parent generateParent(String loginId, String phoneNumber, String residentRegistr Parent parent = Parent.builder() .loginId(loginId) .password("비밀번호") - .nickname("별명") + .nickname(loginId + "별명") .name("이름") .age("20") .gender(남) From a94d20641df2c96b8b8b5867e63fe9662b7088db Mon Sep 17 00:00:00 2001 From: dfdrdodm95 Date: Sun, 5 May 2024 20:04:25 +0900 Subject: [PATCH 3/9] =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=EC=8B=A4=EC=88=98=20?= =?UTF-8?q?=EA=B0=80=EB=8A=A5=EC=84=B1=EC=9D=B4=20=EB=86=92=EC=9D=80=20ini?= =?UTF-8?q?tDb=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kidsqueue/common/forTest/initDb.java | 87 ------------------- 1 file changed, 87 deletions(-) delete mode 100644 src/main/java/com/kidsqueue/kidsqueue/common/forTest/initDb.java diff --git a/src/main/java/com/kidsqueue/kidsqueue/common/forTest/initDb.java b/src/main/java/com/kidsqueue/kidsqueue/common/forTest/initDb.java deleted file mode 100644 index 2261510..0000000 --- a/src/main/java/com/kidsqueue/kidsqueue/common/forTest/initDb.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.kidsqueue.kidsqueue.common.forTest; - -import com.kidsqueue.kidsqueue.hospital.db.Hospital; -import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; -import com.kidsqueue.kidsqueue.hospital.db.enums.Status; -import com.kidsqueue.kidsqueue.parent.db.Parent; -import com.kidsqueue.kidsqueue.parent.db.ParentRepository; -import com.kidsqueue.kidsqueue.review.db.ReviewRepository; -import com.kidsqueue.kidsqueue.review.model.Review; -import jakarta.annotation.PostConstruct; -import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; -import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; - -@Service -@RequiredArgsConstructor -public class initDb { - - /** - * test 용도로 DB에 초기 데이터를 넣어주는 클래스 - */ - - @Autowired private final HospitalRepository hospitalRepository; - @Autowired private final ParentRepository parentRepository; - @Autowired private final ReviewRepository reviewRepository; - @PostConstruct - void init() { - setUp(); - } - - - void setUp() { - Hospital hospital1 = generateHospital("병원1", "000-0000-0001"); - Hospital hospital2 = generateHospital("병원2", "000-0000-0002"); - - Parent parent1 = generateParent("testSignUp1", "010-0000-0001", "0000000000000", "testSignUp@naver.com"); - Parent parent2 = generateParent("testSignUp2", "010-0000-0002", "0000000000001", "testSignUp2@naver.com"); - - generateReview("리뷰1", hospital1, parent1); - generateReview("리뷰2", hospital2, parent2); - } - - Hospital generateHospital(String name, String phoneNumber) { - Hospital hospital = Hospital.builder() - .name(name) - .address(name + "주소") - .description(name + "설명") - .phoneNumber(phoneNumber) - .maxNumOfPeople(5) - .status(Status.OPEN) - .build(); - hospitalRepository.save(hospital); - - return hospital; - } - - Parent generateParent(String loginId, String phoneNumber, String residentRegistrationNumber, String email) { - Parent parent = Parent.builder() - .loginId(loginId) - .password("비밀번호") - .nickname(loginId + "별명") - .name("이름") - .age("20") - .gender(남) - .phoneNumber(phoneNumber) - .residentRegistrationNumber(residentRegistrationNumber) - .email(email) - .role(USER) - .build(); - parentRepository.save(parent); - return parent; - } - - void generateReview(String title, Hospital hospital, Parent parent) { - Review review = Review.builder() - .title(title) - .score(5) - .description(title + "설명") - .hospital(hospital) - .parent(parent) - .build(); - reviewRepository.save(review); - } -} From 1c1197d0af177a7abb304d0928b701ba3c4ee43e Mon Sep 17 00:00:00 2001 From: dfdrdodm95 Date: Sun, 5 May 2024 20:42:02 +0900 Subject: [PATCH 4/9] =?UTF-8?q?objectMapper=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java b/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java index 4e4e756..bb19c01 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java +++ b/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java @@ -2,18 +2,20 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; public class MyObjectMapper { private static ObjectMapper objectMapper; private MyObjectMapper() {} public static String convertToJson(Object obj) throws JsonProcessingException { - return objectMapper.writeValueAsString(obj); + return getInstance().writeValueAsString(obj); } public static ObjectMapper getInstance() { if (objectMapper == null) { objectMapper = new ObjectMapper(); + objectMapper.registerModule(new JavaTimeModule()); } return objectMapper; } From c3802d882935a2e9500e29ab76baaaead9361d9d Mon Sep 17 00:00:00 2001 From: dfdrdodm95 Date: Wed, 8 May 2024 15:50:15 +0900 Subject: [PATCH 5/9] =?UTF-8?q?swagger-ui=20=EB=B0=98=EC=98=81=20=EB=B0=8F?= =?UTF-8?q?=20Exception=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20=20=20=20=20*=20json=20=EB=B3=80=ED=99=98=20=EC=9A=A9?= =?UTF-8?q?=EB=8F=84=EC=9D=98=20string=EC=9D=84=20=EC=A0=84=EB=8B=AC?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B2=8C=20=EC=95=84=EB=8B=88=EB=9D=BC=20?= =?UTF-8?q?=20=20=20=20*=20ReviewDto=20=EA=B3=B5=ED=86=B5=20=EC=9D=B8?= =?UTF-8?q?=ED=84=B0=ED=8E=98=EC=9D=B4=EC=8A=A4=EB=A5=BC=20=EA=B7=B8?= =?UTF-8?q?=EB=8C=80=EB=A1=9C=20=EC=A0=84=EB=8B=AC=ED=95=98=EB=8A=94=20?= =?UTF-8?q?=ED=98=95=EC=8B=9D=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kidsqueue/common/util/MyObjectMapper.java | 22 -------------- .../objectMapper/ObjectMapperConfig.java | 29 +++++++++++++++++++ .../config/swagger/SwaggerConfig.java | 14 +++++++++ .../kidsqueue/review/dtos/ReviewDto.java | 11 ------- .../review/exception/ReviewException.java | 17 ++++++----- .../review/service/ReviewService.java | 6 ++-- 6 files changed, 55 insertions(+), 44 deletions(-) delete mode 100644 src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/config/objectMapper/ObjectMapperConfig.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/config/swagger/SwaggerConfig.java diff --git a/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java b/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java deleted file mode 100644 index bb19c01..0000000 --- a/src/main/java/com/kidsqueue/kidsqueue/common/util/MyObjectMapper.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.kidsqueue.kidsqueue.common.util; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; - -public class MyObjectMapper { - private static ObjectMapper objectMapper; - - private MyObjectMapper() {} - public static String convertToJson(Object obj) throws JsonProcessingException { - return getInstance().writeValueAsString(obj); - } - - public static ObjectMapper getInstance() { - if (objectMapper == null) { - objectMapper = new ObjectMapper(); - objectMapper.registerModule(new JavaTimeModule()); - } - return objectMapper; - } -} diff --git a/src/main/java/com/kidsqueue/kidsqueue/config/objectMapper/ObjectMapperConfig.java b/src/main/java/com/kidsqueue/kidsqueue/config/objectMapper/ObjectMapperConfig.java new file mode 100644 index 0000000..1d9cd5f --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/config/objectMapper/ObjectMapperConfig.java @@ -0,0 +1,29 @@ +package com.kidsqueue.kidsqueue.config.objectMapper; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategy; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + + +@Configuration +public class ObjectMapperConfig { + + @Bean + public ObjectMapper objectMapper() { + ObjectMapper objectMapper = new ObjectMapper(); + + objectMapper.registerModule(new Jdk8Module()) + .registerModule(new JavaTimeModule()) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) + .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) + .setPropertyNamingStrategy(new PropertyNamingStrategy.SnakeCaseStrategy()); + + return objectMapper; + } +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/config/swagger/SwaggerConfig.java b/src/main/java/com/kidsqueue/kidsqueue/config/swagger/SwaggerConfig.java new file mode 100644 index 0000000..91da5a3 --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/config/swagger/SwaggerConfig.java @@ -0,0 +1,14 @@ +package com.kidsqueue.kidsqueue.config.swagger; + +import com.fasterxml.jackson.databind.ObjectMapper; +import io.swagger.v3.core.jackson.ModelResolver; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + @Bean + public ModelResolver modelResolver(ObjectMapper objectMapper) { + return new ModelResolver(objectMapper); + } +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java index 96b0be4..093d09e 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java @@ -1,15 +1,4 @@ package com.kidsqueue.kidsqueue.review.dtos; -import com.fasterxml.jackson.core.JsonProcessingException; - -import static com.kidsqueue.kidsqueue.common.util.MyObjectMapper.convertToJson; - public interface ReviewDto { - default String toJson() { - try { - return convertToJson(this); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java index 11842b9..fa93e1c 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java @@ -1,6 +1,7 @@ package com.kidsqueue.kidsqueue.review.exception; import com.kidsqueue.kidsqueue.common.error.ErrorCode; +import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -9,40 +10,40 @@ public class ReviewException extends RuntimeException { private final ErrorCode errorCode; private final String description; - private final String jsonData; + private final ReviewDto reviewDto; public ReviewException(ErrorCode errorCode) { super(errorCode.getDescription()); this.errorCode = errorCode; this.description = errorCode.getDescription(); - this.jsonData = null; + this.reviewDto = null; } public ReviewException(ErrorCode errorCode, String description) { super(description); this.errorCode = errorCode; this.description = description; - this.jsonData = null; + this.reviewDto = null; } - public ReviewException(String jsonData, ErrorCode errorCode) { + public ReviewException(ErrorCode errorCode, ReviewDto reviewDto) { super(errorCode.getDescription()); this.errorCode = errorCode; this.description = errorCode.getDescription(); - this.jsonData = jsonData; + this.reviewDto = reviewDto; } - public ReviewException(String jsonData, ErrorCode errorCode, String description) { + public ReviewException(ErrorCode errorCode, String description, ReviewDto reviewDto) { super(description); this.errorCode = errorCode; this.description = description; - this.jsonData = jsonData; + this.reviewDto = reviewDto; } public ReviewException(ErrorCode errorCode, Throwable throwable) { super(throwable); this.errorCode = errorCode; this.description = errorCode.getDescription(); - this.jsonData = null; + this.reviewDto = null; } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java b/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java index 3b70008..a4daa9b 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java @@ -79,9 +79,9 @@ public Api findReviewById(Long id) { // TODO : 일치하지 않는 필드 일체를 전달하는 방법이 있으면 좋겠음 public Api createReview(ReviewCreateDto createDto) { Hospital hospital = hospitalRepository.findById(createDto.getHospitalId()) - .orElseThrow(() -> new ReviewException(createDto.toJson(), Hospital_Not_Found)); + .orElseThrow(() -> new ReviewException(Hospital_Not_Found, createDto)); Parent parent = parentRepository.findById(createDto.getParentId()) - .orElseThrow(() -> new ReviewException(createDto.toJson(), Parent_Not_Found)); + .orElseThrow(() -> new ReviewException(Parent_Not_Found, createDto)); Review review = createDto.toEntity(hospital, parent); reviewRepository.save(review); @@ -94,7 +94,7 @@ public Api createReview(ReviewCreateDto createDto) { public Api updateReview(Long id, ReviewUpdateDto updateDto) { Review review = reviewRepository.findById(id) - .orElseThrow(() -> new ReviewException(updateDto.toJson(), Review_Not_Found)); + .orElseThrow(() -> new ReviewException(Review_Not_Found, updateDto)); review.setTitle(updateDto.getTitle()); review.setScore(updateDto.getScore()); From 6ca39175a7bf7f48f81ab686ed226356a15b7c61 Mon Sep 17 00:00:00 2001 From: dfdrdodm95 Date: Thu, 9 May 2024 11:42:14 +0900 Subject: [PATCH 6/9] =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20DTO=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/dtos/ReviewCreateDto.java | 5 +++++ .../kidsqueue/review/dtos/ReviewDto.java | 2 ++ .../kidsqueue/review/dtos/ReviewReadDto.java | 4 ++++ .../review/dtos/ReviewUpdateDto.java | 5 +++++ .../review/exception/ReviewException.java | 4 ++++ .../exception/ReviewExceptionHandler.java | 21 ++++++++++++++----- 6 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java index b629c9e..2f37f47 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java @@ -29,4 +29,9 @@ public Review toEntity(Hospital hospital, Parent parent) { .parent(parent) .build(); } + + @Override + public ReviewDto getInstance() { + return this; + } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java index 093d09e..f18df68 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java @@ -1,4 +1,6 @@ package com.kidsqueue.kidsqueue.review.dtos; + public interface ReviewDto { + public ReviewDto getInstance(); } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java index be00a7b..ac9a839 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java @@ -26,4 +26,8 @@ public Review toEntity() { .build(); } + @Override + public ReviewDto getInstance() { + return this; + } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java index b0e59ff..75a77bd 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java @@ -21,4 +21,9 @@ public Review toEntity() { .description(description) .build(); } + + @Override + public ReviewDto getInstance() { + return this; + } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java index fa93e1c..50ac393 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java @@ -46,4 +46,8 @@ public ReviewException(ErrorCode errorCode, Throwable throwable) { this.description = errorCode.getDescription(); this.reviewDto = null; } + + public ReviewDto getReviewDto() { + return reviewDto.getInstance(); + } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java index 3120185..f714d81 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java @@ -1,6 +1,7 @@ package com.kidsqueue.kidsqueue.review.exception; import com.kidsqueue.kidsqueue.common.Api; +import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; import jakarta.annotation.Priority; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -13,17 +14,27 @@ @Priority(0) @RestControllerAdvice(basePackages = "com.kidsqueue.kidsqueue.review") public class ReviewExceptionHandler { - // TODO : ResponseEntity 형태로 반환하도록 다시 고칠 예정임 - // @ExceptionHandler(value = ReviewException.class) - public Api reviewExceptionHandler(ReviewException reviewException) { + public ResponseEntity> reviewExceptionHandler(ReviewException reviewException) { log.error("", reviewException); HttpStatus httpStatus = reviewException.getErrorCode().getHttpStatusCode(); - return Api.builder() + Api response = Api.builder() + .data(reviewException.getReviewDto()) .status(getFullHttpStatus(httpStatus)) - .message(reviewException.getMessage()) + .message(reviewException.getMessage() + "Handler works") .build(); + + return ResponseEntity + .status(httpStatus) + .body(response); + } + @ExceptionHandler(value = RuntimeException.class) + public ResponseEntity commonExceptionHandler(RuntimeException runtimeException) { + + return ResponseEntity + .status(HttpStatus.BAD_REQUEST) + .body(runtimeException.getCause().getMessage()); } @ExceptionHandler(MethodArgumentNotValidException.class) From 6e243ec87d671b112369168acde8fd22c91d8cf9 Mon Sep 17 00:00:00 2001 From: dfdrdodm95 Date: Thu, 9 May 2024 12:24:27 +0900 Subject: [PATCH 7/9] =?UTF-8?q?=EC=9E=98=EB=AA=BB=EB=90=9C=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20?= =?UTF-8?q?json=20=EC=88=9C=ED=99=98=20=EC=B0=B8=EC=A1=B0=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../review/controller/ReviewController.java | 13 +++++++++---- .../kidsqueue/review/dtos/ReviewCreateDto.java | 4 ---- .../kidsqueue/kidsqueue/review/dtos/ReviewDto.java | 1 - .../kidsqueue/review/dtos/ReviewReadDto.java | 4 ---- .../kidsqueue/review/dtos/ReviewUpdateDto.java | 4 ---- .../kidsqueue/review/exception/ReviewException.java | 8 +++----- .../review/exception/ReviewExceptionHandler.java | 2 +- 7 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java b/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java index 9e62fa5..41ebad5 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java @@ -1,13 +1,19 @@ package com.kidsqueue.kidsqueue.review.controller; import com.kidsqueue.kidsqueue.common.Api; +import com.kidsqueue.kidsqueue.hospital.db.Hospital; import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; +import com.kidsqueue.kidsqueue.hospital.db.enums.Status; +import com.kidsqueue.kidsqueue.parent.db.Parent; import com.kidsqueue.kidsqueue.parent.db.ParentRepository; import com.kidsqueue.kidsqueue.review.db.ReviewRepository; import com.kidsqueue.kidsqueue.review.dtos.ReviewCreateDto; +import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; import com.kidsqueue.kidsqueue.review.dtos.ReviewReadDto; import com.kidsqueue.kidsqueue.review.dtos.ReviewUpdateDto; +import com.kidsqueue.kidsqueue.review.model.Review; import com.kidsqueue.kidsqueue.review.service.ReviewService; +import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; @@ -18,6 +24,9 @@ import java.util.List; +import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; +import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; + @RestController @RequestMapping("/api/review") @RequiredArgsConstructor @@ -25,10 +34,6 @@ public class ReviewController { private final ReviewService reviewService; - @Autowired final ReviewRepository reviewRepository; - @Autowired final private HospitalRepository hospitalRepository; - @Autowired final private ParentRepository parentRepository; - // TODO : 반환 값을 바꿔볼까 고민 중 // TODO : 동작 안 함 /api/review?sortCondition=desc로 url 입력한 결과. diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java index 2f37f47..8d3799b 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java @@ -30,8 +30,4 @@ public Review toEntity(Hospital hospital, Parent parent) { .build(); } - @Override - public ReviewDto getInstance() { - return this; - } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java index f18df68..e06851e 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java @@ -2,5 +2,4 @@ public interface ReviewDto { - public ReviewDto getInstance(); } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java index ac9a839..be00a7b 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java @@ -26,8 +26,4 @@ public Review toEntity() { .build(); } - @Override - public ReviewDto getInstance() { - return this; - } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java index 75a77bd..00164c3 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java @@ -22,8 +22,4 @@ public Review toEntity() { .build(); } - @Override - public ReviewDto getInstance() { - return this; - } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java index 50ac393..bbc5898 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java @@ -2,9 +2,7 @@ import com.kidsqueue.kidsqueue.common.error.ErrorCode; import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; -import lombok.AllArgsConstructor; import lombok.Getter; -import lombok.RequiredArgsConstructor; @Getter public class ReviewException extends RuntimeException { @@ -47,7 +45,7 @@ public ReviewException(ErrorCode errorCode, Throwable throwable) { this.reviewDto = null; } - public ReviewDto getReviewDto() { - return reviewDto.getInstance(); - } +// public ReviewDto getReviewDto() { +// return reviewDto.getInstance(); +// } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java index f714d81..62e4316 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java @@ -22,7 +22,7 @@ public ResponseEntity> reviewExceptionHandler(ReviewException rev Api response = Api.builder() .data(reviewException.getReviewDto()) .status(getFullHttpStatus(httpStatus)) - .message(reviewException.getMessage() + "Handler works") + .message(reviewException.getMessage()) .build(); return ResponseEntity From cba1f856b6adb26526af4a6bee0690796d9f6d4e Mon Sep 17 00:00:00 2001 From: dfdrdodm95 Date: Mon, 10 Jun 2024 22:42:40 +0900 Subject: [PATCH 8/9] =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EC=82=AC=ED=95=AD?= =?UTF-8?q?=EB=93=A4=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=9E=91=EC=84=B1=20=20=20=20=20*=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EB=8B=A8=EC=9C=84=EA=B0=80=20=EC=95=84?= =?UTF-8?q?=EB=8B=8C=20=EC=83=9D=EC=84=B1=EC=9E=90=20Builder=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9C=BC=EB=A1=9C=20=EB=B3=B4=ED=98=B8=20=EC=88=98?= =?UTF-8?q?=EC=A4=80=20=ED=99=95=EB=B3=B4=20=20=20=20=20*=20Response=20DTO?= =?UTF-8?q?=20=EC=9E=91=EC=84=B1=EA=B3=BC=20=EA=B7=B8=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kidsqueue/common/BaseEntity.java | 10 +- .../review/controller/ReviewController.java | 35 +-- .../kidsqueue/kidsqueue/review/db/Review.java | 39 ++++ .../kidsqueue/review/db/ReviewRepository.java | 1 - .../review/dtos/ReviewCreateDto.java | 33 --- .../kidsqueue/review/dtos/ReviewDto.java | 5 - .../kidsqueue/review/dtos/ReviewReadDto.java | 29 --- .../review/dtos/ReviewUpdateDto.java | 25 --- .../review/exception/ReviewException.java | 2 +- .../exception/ReviewExceptionHandler.java | 2 +- .../kidsqueue/review/model/Review.java | 34 --- .../review/model/ReviewCreateRequest.java | 46 ++++ .../review/model/ReviewCreateResponse.java | 41 ++++ .../kidsqueue/review/model/ReviewDto.java | 5 + .../review/model/ReviewReadResponse.java | 40 ++++ .../review/model/ReviewUpdateRequest.java | 36 +++ .../review/model/ReviewUpdateResponse.java | 31 +++ .../review/service/ReviewConverter.java | 25 --- .../review/service/ReviewService.java | 75 +++---- .../kidsqueue/medium/ReviewServiceTest.java | 206 ++++++++++++++++++ .../review/db/ReviewRepositoryTest.java | 90 ++++++++ .../review/service/ReviewServiceTest.java | 180 +-------------- 22 files changed, 588 insertions(+), 402 deletions(-) create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/db/Review.java delete mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java delete mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java delete mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java delete mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java delete mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/model/Review.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewCreateRequest.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewCreateResponse.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewDto.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewReadResponse.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateRequest.java create mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateResponse.java delete mode 100644 src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewConverter.java create mode 100644 src/test/java/com/kidsqueue/kidsqueue/medium/ReviewServiceTest.java create mode 100644 src/test/java/com/kidsqueue/kidsqueue/review/db/ReviewRepositoryTest.java diff --git a/src/main/java/com/kidsqueue/kidsqueue/common/BaseEntity.java b/src/main/java/com/kidsqueue/kidsqueue/common/BaseEntity.java index 8bf6a75..a2d6e9d 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/common/BaseEntity.java +++ b/src/main/java/com/kidsqueue/kidsqueue/common/BaseEntity.java @@ -16,9 +16,9 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; @MappedSuperclass -@Data -@SuperBuilder -@NoArgsConstructor +@Data // TODO : data 어노테이션의 위험성 상 제거하는 게 좋을 듯함 +@SuperBuilder(builderMethodName = "superBuilder") +@NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor @EntityListeners(AuditingEntityListener.class) // 생성 일자, 수정 일자 자동으로 채워줌 public class BaseEntity { // 공통 속성을 묶는 엔티티 @@ -40,4 +40,8 @@ public class BaseEntity { // 공통 속성을 묶는 엔티티 public boolean isActive() { // 데이터베이스 저장용 : Integer, 실제 로직용: boolean return isActive != null && isActive == 1; } + + public void softDelete() { + this.isActive = 0; + } } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java b/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java index 41ebad5..dc8b9cb 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/controller/ReviewController.java @@ -1,21 +1,9 @@ package com.kidsqueue.kidsqueue.review.controller; import com.kidsqueue.kidsqueue.common.Api; -import com.kidsqueue.kidsqueue.hospital.db.Hospital; -import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; -import com.kidsqueue.kidsqueue.hospital.db.enums.Status; -import com.kidsqueue.kidsqueue.parent.db.Parent; -import com.kidsqueue.kidsqueue.parent.db.ParentRepository; -import com.kidsqueue.kidsqueue.review.db.ReviewRepository; -import com.kidsqueue.kidsqueue.review.dtos.ReviewCreateDto; -import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; -import com.kidsqueue.kidsqueue.review.dtos.ReviewReadDto; -import com.kidsqueue.kidsqueue.review.dtos.ReviewUpdateDto; -import com.kidsqueue.kidsqueue.review.model.Review; +import com.kidsqueue.kidsqueue.review.model.*; import com.kidsqueue.kidsqueue.review.service.ReviewService; -import jakarta.annotation.PostConstruct; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PageableDefault; import org.springframework.http.HttpStatus; @@ -24,9 +12,6 @@ import java.util.List; -import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; -import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; - @RestController @RequestMapping("/api/review") @RequiredArgsConstructor @@ -39,13 +24,13 @@ public class ReviewController { // TODO : 동작 안 함 /api/review?sortCondition=desc로 url 입력한 결과. // 디버깅 필요함 @GetMapping - public Api> get( + public Api> get( @PageableDefault(page = 0, size = 10) Pageable pageable, @RequestParam(required = false) String sortCondition ) { System.out.println("sortCondition = " + sortCondition); - Api> apiResponse; + Api> apiResponse; if ("desc".equals(sortCondition)) { apiResponse = reviewService.findAllDesc(pageable); @@ -60,8 +45,8 @@ public Api> get( } @GetMapping("/{review_id}") - public ResponseEntity> getReviewById(@PathVariable("review_id") Long id) { - Api apiResponse = reviewService.findReviewById(id); + public ResponseEntity> getReviewById(@PathVariable("review_id") Long id) { + Api apiResponse = reviewService.findReviewById(id); if (apiResponse.getData() != null) { apiResponse.setStatus(Api.SUCCESS_STATUS); @@ -75,8 +60,8 @@ public ResponseEntity> getReviewById(@PathVariable("review_id } @PostMapping - public ResponseEntity> createReview(@RequestBody ReviewCreateDto reviewCreateDto) { - Api apiResponse = reviewService.createReview(reviewCreateDto); + public ResponseEntity> createReview(@RequestBody ReviewCreateRequest reviewCreateRequest) { + Api apiResponse = reviewService.createReview(reviewCreateRequest); if (apiResponse.getData() != null) { apiResponse.setStatus(Api.SUCCESS_STATUS); @@ -90,9 +75,9 @@ public ResponseEntity> createReview(@RequestBody ReviewCrea } @PatchMapping("/{review_id}") - public ResponseEntity> updateReview(@PathVariable("review_id") Long id, - @RequestBody ReviewUpdateDto updateDto) { - Api apiResponse = reviewService.updateReview(id, updateDto); + public ResponseEntity> updateReview(@PathVariable("review_id") Long id, + @RequestBody ReviewUpdateRequest updateDto) { + Api apiResponse = reviewService.updateReview(id, updateDto); if (apiResponse.getData() != null) { apiResponse.setStatus(Api.SUCCESS_STATUS); diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/db/Review.java b/src/main/java/com/kidsqueue/kidsqueue/review/db/Review.java new file mode 100644 index 0000000..b00edde --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/db/Review.java @@ -0,0 +1,39 @@ +package com.kidsqueue.kidsqueue.review.db; + +import com.kidsqueue.kidsqueue.common.BaseEntity; +import com.kidsqueue.kidsqueue.hospital.db.Hospital; +import com.kidsqueue.kidsqueue.parent.db.Parent; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +@Table(name = "review") +public class Review extends BaseEntity { + private String title; + private Integer score; + private String description; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "hospital_id") + private Hospital hospital; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "parent_id") + private Parent parent; + + @Builder + public Review(Long id, Integer isActive, LocalDateTime createdBy, LocalDateTime updatedBy, String title, Integer score, String description, Hospital hospital, Parent parent) { + super(id, isActive, createdBy, updatedBy); + this.title = title; + this.score = score; + this.description = description; + this.hospital = hospital; + this.parent = parent; + } +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/db/ReviewRepository.java b/src/main/java/com/kidsqueue/kidsqueue/review/db/ReviewRepository.java index fa49bc6..139907f 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/db/ReviewRepository.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/db/ReviewRepository.java @@ -1,6 +1,5 @@ package com.kidsqueue.kidsqueue.review.db; -import com.kidsqueue.kidsqueue.review.model.Review; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java deleted file mode 100644 index 8d3799b..0000000 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewCreateDto.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.kidsqueue.kidsqueue.review.dtos; - -import com.kidsqueue.kidsqueue.hospital.db.Hospital; -import com.kidsqueue.kidsqueue.parent.db.Parent; -import com.kidsqueue.kidsqueue.review.model.Review; -import jakarta.validation.constraints.NotBlank; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class ReviewCreateDto implements ReviewDto { - @NotBlank - private String title; - @NotBlank - private Integer score; - private String description; - @NotBlank - private Long hospitalId; - @NotBlank - private Long parentId; - - public Review toEntity(Hospital hospital, Parent parent) { - return Review.builder() - .title(title) - .score(score) - .description(description) - .hospital(hospital) - .parent(parent) - .build(); - } - -} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java deleted file mode 100644 index e06851e..0000000 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewDto.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.kidsqueue.kidsqueue.review.dtos; - - -public interface ReviewDto { -} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java deleted file mode 100644 index be00a7b..0000000 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewReadDto.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.kidsqueue.kidsqueue.review.dtos; - -import com.kidsqueue.kidsqueue.review.model.Review; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.experimental.SuperBuilder; - -import java.time.LocalDateTime; - -@Getter -@NoArgsConstructor -@AllArgsConstructor -@SuperBuilder -public class ReviewReadDto implements ReviewDto { - private String title; - private Integer score; - private String description; - private LocalDateTime createdBy; - public Review toEntity() { - return Review.builder() - .title(title) - .score(score) - .description(description) - .createdBy(createdBy) - .build(); - } - -} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java deleted file mode 100644 index 00164c3..0000000 --- a/src/main/java/com/kidsqueue/kidsqueue/review/dtos/ReviewUpdateDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.kidsqueue.kidsqueue.review.dtos; - -import com.kidsqueue.kidsqueue.review.model.Review; -import jakarta.validation.constraints.NotBlank; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class ReviewUpdateDto implements ReviewDto { - @NotBlank - private String title; - @NotBlank - private Integer score; - private String description; - - public Review toEntity() { - return Review.builder() - .title(title) - .score(score) - .description(description) - .build(); - } - -} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java index bbc5898..20a4114 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewException.java @@ -1,7 +1,7 @@ package com.kidsqueue.kidsqueue.review.exception; import com.kidsqueue.kidsqueue.common.error.ErrorCode; -import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; +import com.kidsqueue.kidsqueue.review.model.ReviewDto; import lombok.Getter; @Getter diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java index 62e4316..ac153b8 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/exception/ReviewExceptionHandler.java @@ -1,7 +1,7 @@ package com.kidsqueue.kidsqueue.review.exception; import com.kidsqueue.kidsqueue.common.Api; -import com.kidsqueue.kidsqueue.review.dtos.ReviewDto; +import com.kidsqueue.kidsqueue.review.model.ReviewDto; import jakarta.annotation.Priority; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/model/Review.java b/src/main/java/com/kidsqueue/kidsqueue/review/model/Review.java deleted file mode 100644 index 4c97fc7..0000000 --- a/src/main/java/com/kidsqueue/kidsqueue/review/model/Review.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.kidsqueue.kidsqueue.review.model; - -import com.kidsqueue.kidsqueue.common.BaseEntity; -import com.kidsqueue.kidsqueue.hospital.db.Hospital; -import com.kidsqueue.kidsqueue.parent.db.Parent; -import jakarta.persistence.*; -import lombok.*; -import lombok.experimental.SuperBuilder; - -import java.time.LocalDate; -import java.time.LocalDateTime; - -@Getter -@Setter -@NoArgsConstructor -@AllArgsConstructor -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -@SuperBuilder -@Entity -@Table(name = "review") -public class Review extends BaseEntity { - private String title; - private Integer score; - private String description; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "hospital_id") - private Hospital hospital; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "parent_id") - private Parent parent; - -} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewCreateRequest.java b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewCreateRequest.java new file mode 100644 index 0000000..f00a76d --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewCreateRequest.java @@ -0,0 +1,46 @@ +package com.kidsqueue.kidsqueue.review.model; + +import com.kidsqueue.kidsqueue.hospital.db.Hospital; +import com.kidsqueue.kidsqueue.parent.db.Parent; +import com.kidsqueue.kidsqueue.review.db.Review; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; +import org.springframework.util.Assert; + +@Getter +public class ReviewCreateRequest implements ReviewDto { + @NotBlank + private final String title; + @NotNull + private final Integer score; + private final String description; + @NotNull + private final Long hospitalId; + @NotNull + private final Long parentId; + + public Review toEntity(Hospital hospital, Parent parent) { + return Review.builder() + .title(title) + .score(score) + .description(description) + .hospital(hospital) + .parent(parent) + .build(); + } + + @Builder + public ReviewCreateRequest(String title, Integer score, String description, Long hospitalId, Long parentId) { + Assert.hasText(title, "title must not be empty"); + Assert.notNull(score, "score must not be null"); + Assert.notNull(hospitalId, "hospitalId must not be null"); + Assert.notNull(parentId, "parentId must not be null"); + this.title = title; + this.score = score; + this.description = description; + this.hospitalId = hospitalId; + this.parentId = parentId; + } +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewCreateResponse.java b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewCreateResponse.java new file mode 100644 index 0000000..d87534b --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewCreateResponse.java @@ -0,0 +1,41 @@ +package com.kidsqueue.kidsqueue.review.model; + +import com.kidsqueue.kidsqueue.hospital.db.Hospital; +import com.kidsqueue.kidsqueue.parent.db.Parent; +import com.kidsqueue.kidsqueue.review.db.Review; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; +import org.springframework.util.Assert; + +import java.time.LocalDateTime; + +@Getter +public class ReviewCreateResponse { + @NotBlank + private final String title; + @NotNull + private final Integer score; + private final String description; + private final LocalDateTime createdBy; + + @Builder + public ReviewCreateResponse(String title, Integer score, String description, LocalDateTime createdBy) { + Assert.hasText(title, "title must not be empty"); + Assert.notNull(score, "score must not be null"); + this.title = title; + this.score = score; + this.description = description; + this.createdBy = createdBy; + } + + public static ReviewCreateResponse fromEntity(Review review) { + return ReviewCreateResponse.builder() + .title(review.getTitle()) + .score(review.getScore()) + .description(review.getDescription()) + .createdBy(review.getCreatedBy()) + .build(); + } +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewDto.java b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewDto.java new file mode 100644 index 0000000..e534b9f --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewDto.java @@ -0,0 +1,5 @@ +package com.kidsqueue.kidsqueue.review.model; + + +public interface ReviewDto { +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewReadResponse.java b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewReadResponse.java new file mode 100644 index 0000000..1796eb9 --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewReadResponse.java @@ -0,0 +1,40 @@ +package com.kidsqueue.kidsqueue.review.model; + +import com.kidsqueue.kidsqueue.review.db.Review; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; +import org.springframework.util.Assert; + +import java.time.LocalDateTime; + +@Getter +public class ReviewReadResponse implements ReviewDto { + @NotBlank + private final String title; + @NotNull + private final Integer score; + private final String description; + @NotNull + private final LocalDateTime createdBy; + + @Builder + public ReviewReadResponse(String title, Integer score, String description, LocalDateTime createdBy) { + Assert.hasText(title, "title must not be empty"); + Assert.notNull(score, "score must not be null"); + this.title = title; + this.score = score; + this.description = description; + this.createdBy = createdBy; + } + + public static ReviewReadResponse fromEntity(Review review) { + return ReviewReadResponse.builder() + .title(review.getTitle()) + .score(review.getScore()) + .description(review.getDescription()) + .createdBy(review.getCreatedBy()) + .build(); + } +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateRequest.java b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateRequest.java new file mode 100644 index 0000000..fed8a6c --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateRequest.java @@ -0,0 +1,36 @@ +package com.kidsqueue.kidsqueue.review.model; + +import com.kidsqueue.kidsqueue.review.db.Review; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; +import org.springframework.util.Assert; + +@Getter +public class ReviewUpdateRequest implements ReviewDto { + @NotBlank + private String title; + @NotNull + private Integer score; + private String description; + + @Builder + public ReviewUpdateRequest(String title, Integer score, String description) { + Assert.hasText(title, "title must not be empty"); + Assert.notNull(score, "score must not be null"); + this.title = title; + this.score = score; + this.description = description; + } + + public Review toEntity(Long id) { + return Review.builder() + .id(id) + .title(title) + .score(score) + .description(description) + .build(); + } + +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateResponse.java b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateResponse.java new file mode 100644 index 0000000..09f333d --- /dev/null +++ b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateResponse.java @@ -0,0 +1,31 @@ +package com.kidsqueue.kidsqueue.review.model; + +import com.kidsqueue.kidsqueue.review.db.Review; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import org.springframework.util.Assert; + +public class ReviewUpdateResponse { + @NotBlank + private final String title; + @NotNull + private final Integer score; + private final String description; + @Builder + public ReviewUpdateResponse(String title, Integer score, String description) { + Assert.hasText(title, "title must not be empty"); + Assert.notNull(score, "score must not be null"); + this.title = title; + this.score = score; + this.description = description; + } + + public static ReviewUpdateResponse fromEntity(Review review) { + return ReviewUpdateResponse.builder() + .title(review.getTitle()) + .score(review.getScore()) + .description(review.getDescription()) + .build(); + } +} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewConverter.java b/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewConverter.java deleted file mode 100644 index 0f2fed2..0000000 --- a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewConverter.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.kidsqueue.kidsqueue.review.service; - -import com.kidsqueue.kidsqueue.review.model.Review; -import com.kidsqueue.kidsqueue.review.dtos.ReviewReadDto; -import org.springframework.stereotype.Service; - -@Service -public class ReviewConverter { - public ReviewReadDto toDto(Review review) { - return ReviewReadDto.builder() - .title(review.getTitle()) - .score(review.getScore()) - .description(review.getDescription()) - .createdBy(review.getCreatedBy()) - .build(); - } - - public Review toEntity(ReviewReadDto reviewReadDto) { - return Review.builder() - .title(reviewReadDto.getTitle()) - .description(reviewReadDto.getDescription()) - .score(reviewReadDto.getScore()) - .build(); - } -} diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java b/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java index a4daa9b..6f1bf62 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/service/ReviewService.java @@ -6,16 +6,13 @@ import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; import com.kidsqueue.kidsqueue.parent.db.Parent; import com.kidsqueue.kidsqueue.parent.db.ParentRepository; -import com.kidsqueue.kidsqueue.review.exception.ReviewErrorCode; import com.kidsqueue.kidsqueue.review.exception.ReviewException; -import com.kidsqueue.kidsqueue.review.model.Review; +import com.kidsqueue.kidsqueue.review.db.Review; import com.kidsqueue.kidsqueue.review.db.ReviewRepository; -import com.kidsqueue.kidsqueue.review.dtos.ReviewReadDto; +import com.kidsqueue.kidsqueue.review.model.*; + import java.util.List; -import java.util.Optional; -import com.kidsqueue.kidsqueue.review.dtos.ReviewCreateDto; -import com.kidsqueue.kidsqueue.review.dtos.ReviewUpdateDto; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -29,55 +26,53 @@ public class ReviewService { private final ReviewRepository reviewRepository; private final HospitalRepository hospitalRepository; private final ParentRepository parentRepository; - private final ReviewConverter reviewConverter; - public Api> findAllAsc(Pageable pageable) { + public Api> findAllAsc(Pageable pageable) { // Page 를 Page 로 변환 - Page reviewDtoPage = reviewRepository.findAllByIsActiveOrderByIdAsc(1, pageable) - .map(reviewConverter::toDto); - return getApiResponse(reviewDtoPage); + Page page = reviewRepository.findAllByIsActiveOrderByIdAsc(1, pageable) + .map(ReviewReadResponse::fromEntity); + return getApiResponse(page); } - public Api> findAllDesc(Pageable pageable) { - Page reviewDtoPage = reviewRepository.findAllByIsActiveOrderByIdDesc(1, pageable) - .map(reviewConverter::toDto); - return getApiResponse(reviewDtoPage); + public Api> findAllDesc(Pageable pageable) { + Page page = reviewRepository.findAllByIsActiveOrderByIdDesc(1, pageable) + .map(ReviewReadResponse::fromEntity); + return getApiResponse(page); } - private static Api> getApiResponse(Page reviewDtoPage) { - List reviewReadDtoList = reviewDtoPage.toList(); + private static Api> getApiResponse(Page response) { + List list = response.toList(); // Page 로 pagination 생성 Pagination pagination = Pagination.builder() - .page(reviewDtoPage.getNumber()) - .size(reviewDtoPage.getSize()) - .currentElements(reviewDtoPage.getNumberOfElements()) - .totalElements(reviewDtoPage.getTotalElements()) - .totalPage(reviewDtoPage.getTotalPages()) + .page(response.getNumber()) + .size(response.getSize()) + .currentElements(response.getNumberOfElements()) + .totalElements(response.getTotalElements()) + .totalPage(response.getTotalPages()) .build(); // ApiResponse> 만들어서 리턴 - return Api.>builder() - .data(reviewReadDtoList) + return Api.>builder() + .data(list) .pagination(pagination) .build(); } - public Api findReviewById(Long id) { + public Api findReviewById(Long id) { Review review = reviewRepository.findByIdAndIsActive(id, 1) .orElseThrow(() -> new ReviewException(Review_Not_Found)); - ReviewReadDto reviewReadDto = reviewConverter.toDto(review); - return Api.builder() - .data(reviewReadDto) + ReviewReadResponse reviewReadResponse = ReviewReadResponse.fromEntity(review); + return Api.builder() + .data(reviewReadResponse) .status(Api.SUCCESS_STATUS) .message("리뷰 정보 조회 성공") .build(); } - // TODO : 일치하지 않는 필드 일체를 전달하는 방법이 있으면 좋겠음 - public Api createReview(ReviewCreateDto createDto) { + public Api createReview(ReviewCreateRequest createDto) { Hospital hospital = hospitalRepository.findById(createDto.getHospitalId()) .orElseThrow(() -> new ReviewException(Hospital_Not_Found, createDto)); Parent parent = parentRepository.findById(createDto.getParentId()) @@ -85,25 +80,22 @@ public Api createReview(ReviewCreateDto createDto) { Review review = createDto.toEntity(hospital, parent); reviewRepository.save(review); - return Api.builder() - .data(createDto) + return Api.builder() + .data(ReviewCreateResponse.fromEntity(review)) .status(Api.SUCCESS_STATUS) .message("리뷰 정보 생성 성공") .build(); } - public Api updateReview(Long id, ReviewUpdateDto updateDto) { + public Api updateReview(Long id, ReviewUpdateRequest updateDto) { Review review = reviewRepository.findById(id) .orElseThrow(() -> new ReviewException(Review_Not_Found, updateDto)); - review.setTitle(updateDto.getTitle()); - review.setScore(updateDto.getScore()); - review.setDescription(updateDto.getDescription()); - - Review updatedReview = reviewRepository.save(review); + Review saved = updateDto.toEntity(review.getId()); + reviewRepository.save(saved); - return Api.builder() - .data(updateDto) + return Api.builder() + .data(ReviewUpdateResponse.fromEntity(saved)) .status(Api.SUCCESS_STATUS) .message("리뷰 정보 수정 성공") .build(); @@ -113,8 +105,7 @@ public Api deleteReview(Long id) { Review review = reviewRepository.findById(id) .orElseThrow(() -> new ReviewException(Review_Not_Found)); - review.setIsActive(0); - Review inactivatedReview = reviewRepository.save(review); + review.softDelete(); return Api.builder() .status(Api.SUCCESS_STATUS) diff --git a/src/test/java/com/kidsqueue/kidsqueue/medium/ReviewServiceTest.java b/src/test/java/com/kidsqueue/kidsqueue/medium/ReviewServiceTest.java new file mode 100644 index 0000000..71366c7 --- /dev/null +++ b/src/test/java/com/kidsqueue/kidsqueue/medium/ReviewServiceTest.java @@ -0,0 +1,206 @@ +package com.kidsqueue.kidsqueue.medium; + +import com.kidsqueue.kidsqueue.common.Api; +import com.kidsqueue.kidsqueue.hospital.db.Hospital; +import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; +import com.kidsqueue.kidsqueue.hospital.db.enums.Status; +import com.kidsqueue.kidsqueue.parent.db.Parent; +import com.kidsqueue.kidsqueue.parent.db.ParentRepository; +import com.kidsqueue.kidsqueue.review.db.Review; +import com.kidsqueue.kidsqueue.review.db.ReviewRepository; +import com.kidsqueue.kidsqueue.review.exception.ReviewErrorCode; +import com.kidsqueue.kidsqueue.review.exception.ReviewException; +import com.kidsqueue.kidsqueue.review.model.*; +import com.kidsqueue.kidsqueue.review.service.ReviewService; +import jakarta.transaction.Transactional; +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.PageRequest; + +import java.util.List; +import java.util.Optional; + +import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; +import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@SpringBootTest +@Transactional +class ReviewServiceTest { + @Autowired + ReviewService reviewService; + @Autowired + HospitalRepository hospitalRepository; + @Autowired + ParentRepository parentRepository; + @Autowired + ReviewRepository reviewRepository; + private Hospital hospital; + private Parent parent; + + @BeforeEach + void setUp() { + hospital = createHospital("병원1", "000-0000-0001"); + parent = createParent("testSignUp1", "010-0000-0001", "0000000000000", "testSignUp@naver.com"); + } + + @Test + @DisplayName("리뷰를 오름차순 정렬한다.") + void findAllAsc() { + Review review1 = createReview("리뷰 1", hospital, parent); + Review review2 = createReview("리뷰 2", hospital, parent); + reviewRepository.save(review1); + reviewRepository.save(review2); + PageRequest pageRequest = PageRequest.of(0, 10); + + List list = reviewService.findAllAsc(pageRequest).getData(); + + assertTrue((list.get(list.size() - 2).getCreatedBy().isBefore(list.get(list.size() - 1).getCreatedBy()))); + } + + @Test + @DisplayName("리뷰를 내림차순 정렬한다.") + void findAllDesc() { + Review review1 = createReview("리뷰 1", hospital, parent); + Review review2 = createReview("리뷰 2", hospital, parent); + reviewRepository.save(review1); + reviewRepository.save(review2); + PageRequest pageRequest = PageRequest.of(0, 10); + + List list = reviewService.findAllDesc(pageRequest).getData(); + + assertTrue((list.get(list.size() - 2).getCreatedBy().isAfter(list.get(list.size() - 1).getCreatedBy()))); + } + + @Test + @DisplayName("리뷰 생성에 실패한다. - hospital id 조회 실패") + void createReview_negativeCase_notFound_hospitalId() { + //given + hospitalRepository.delete(hospital); + ReviewCreateRequest request = createReviewCreateRequest("리뷰 1", hospital, parent); + + //when + //then + assertThatThrownBy(() -> { + Api response = reviewService.createReview(request); + }).isInstanceOf(ReviewException.class) + .hasMessageContaining(ReviewErrorCode.Hospital_Not_Found.getDescription()); + } + + + @Test + @DisplayName("리뷰 생성에 실패한다. - parent id 조회 실패") + void createReview_negativeCase_notFound_parentId() { + //given + parentRepository.delete(parent); + ReviewCreateRequest request = createReviewCreateRequest("리뷰 1", hospital, parent); + + //when + //then + assertThatThrownBy(() -> { + Api response = reviewService.createReview(request); + }).isInstanceOf(ReviewException.class) + .hasMessageContaining(ReviewErrorCode.Parent_Not_Found.getDescription()); + } + + // 메서드 시그너쳐 상 동일성 비교가 불가능하므로 repository 테스트로 이를 대체하고 반환값만 검증하였음 + // 테스트 DB가 계속 비어있다는 가정이면, 전체 조회를 2회 시행해서 전후를 비교하고 괜찮은 보호 수준을 확보해도 문제 없을 것. + @Test + @DisplayName("리뷰 생성에 성공한다.") + void createReview_positiveCase() { + ReviewCreateRequest request = createReviewCreateRequest("리뷰 1", hospital, parent); + + Api apiResponse = reviewService.createReview(request); + + Assertions.assertThat(apiResponse.getData().getTitle()).isEqualTo(request.getTitle()); + } + + @Test + @DisplayName("리뷰를 업데이트한다.") + void updateReview() { + Review review = createReview("리뷰1", hospital, parent); + reviewRepository.save(review); + ReviewUpdateRequest request = ReviewUpdateRequest.builder() + .title("리뷰 수정1") + .description("설명 수정1") + .score(1) + .build(); + + Api response = reviewService.updateReview(review.getId(), request); + + Review found = reviewRepository.findById(review.getId()).orElseThrow(()-> new RuntimeException("not found")); + assertThat(found.getTitle()).isEqualTo(request.getTitle()); + } + + @Test + @DisplayName("리뷰를 삭제한다.") + void deleteReview() { + Review review = createReview("리뷰1", hospital, parent); + reviewRepository.save(review); + + reviewService.deleteReview(review.getId()); + + Optional reviewOptional = reviewRepository.findById(review.getId()); + if (reviewOptional.isPresent()) assertEquals(0, reviewOptional.get().getIsActive()); + else Assertions.fail("deleteReview 메서드는 삭제되는 대신 isActive 가 변경돼야 합니다."); + } + + Hospital createHospital(String name, String phoneNumber) { + Hospital hospital = Hospital.builder() + .name(name) + .address(name + "주소") + .description(name + "설명") + .phoneNumber(phoneNumber) + .maxNumOfPeople(5) + .status(Status.OPEN) + .build(); + hospitalRepository.save(hospital); + + return hospital; + } + + Parent createParent(String loginId, String phoneNumber, String residentRegistrationNumber, String email) { + Parent parent = Parent.builder() + .loginId(loginId) + .password("비밀번호") + .nickname(loginId + "별명") + .name("이름") + .age("20") + .gender(남) + .phoneNumber(phoneNumber) + .residentRegistrationNumber(residentRegistrationNumber) + .email(email) + .role(USER) + .build(); + parentRepository.save(parent); + return parent; + } + + Review createReview(String title, Hospital hospital, Parent parent) { + return Review.builder() + .title(title) + .score(5) + .description(title + "설명") + .hospital(hospital) + .parent(parent) + .isActive(1) + .build(); + } + + ReviewCreateRequest createReviewCreateRequest(String title, Hospital hospital, Parent parent) { + return ReviewCreateRequest.builder() + .title(title) + .score(5) + .description(title + " 설명") + .parentId(parent.getId()) + .hospitalId(hospital.getId()) + .build(); + } +} \ No newline at end of file diff --git a/src/test/java/com/kidsqueue/kidsqueue/review/db/ReviewRepositoryTest.java b/src/test/java/com/kidsqueue/kidsqueue/review/db/ReviewRepositoryTest.java new file mode 100644 index 0000000..ca4abf7 --- /dev/null +++ b/src/test/java/com/kidsqueue/kidsqueue/review/db/ReviewRepositoryTest.java @@ -0,0 +1,90 @@ +package com.kidsqueue.kidsqueue.review.db; + +import com.kidsqueue.kidsqueue.hospital.db.Hospital; +import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; +import com.kidsqueue.kidsqueue.hospital.db.enums.Status; +import com.kidsqueue.kidsqueue.parent.db.Parent; +import com.kidsqueue.kidsqueue.parent.db.ParentRepository; +import com.kidsqueue.kidsqueue.review.model.ReviewCreateRequest; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; +import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +class ReviewRepositoryTest { + @Autowired private ReviewRepository reviewRepository; + @Autowired private HospitalRepository hospitalRepository; + @Autowired private ParentRepository parentRepository; + private Hospital hospital; + private Parent parent; + @BeforeEach + void setUp() { + hospital = createHospital("병원1", "000-0000-0001"); + parent = createParent("testSignUp1", "010-0000-0001", "0000000000000", "testSignUp@naver.com"); + } + + @Test + void 리뷰를_저장한다() { + Review review = createReview("리뷰 1", hospital, parent); + + reviewRepository.save(review); + + assertThat(review.getId()).isNotNull(); + } + Hospital createHospital(String name, String phoneNumber) { + Hospital hospital = Hospital.builder() + .name(name) + .address(name + "주소") + .description(name + "설명") + .phoneNumber(phoneNumber) + .maxNumOfPeople(5) + .status(Status.OPEN) + .build(); + hospitalRepository.save(hospital); + + return hospital; + } + + Parent createParent(String loginId, String phoneNumber, String residentRegistrationNumber, String email) { + Parent parent = Parent.builder() + .loginId(loginId) + .password("비밀번호") + .nickname(loginId + "별명") + .name("이름") + .age("20") + .gender(남) + .phoneNumber(phoneNumber) + .residentRegistrationNumber(residentRegistrationNumber) + .email(email) + .role(USER) + .build(); + parentRepository.save(parent); + return parent; + } + + Review createReview(String title, Hospital hospital, Parent parent) { + return Review.builder() + .title(title) + .score(5) + .description(title + "설명") + .hospital(hospital) + .parent(parent) + .isActive(1) + .build(); + } + + ReviewCreateRequest createReviewCreateRequest(String title, Hospital hospital, Parent parent) { + return ReviewCreateRequest.builder() + .title(title) + .score(5) + .description(title + " 설명") + .parentId(parent.getId()) + .hospitalId(hospital.getId()) + .build(); + } +} \ No newline at end of file diff --git a/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java b/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java index f44eabf..02a6b35 100644 --- a/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java +++ b/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java @@ -1,180 +1,4 @@ package com.kidsqueue.kidsqueue.review.service; -import com.kidsqueue.kidsqueue.common.Api; -import com.kidsqueue.kidsqueue.hospital.db.Hospital; -import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; -import com.kidsqueue.kidsqueue.hospital.db.enums.Status; -import com.kidsqueue.kidsqueue.parent.db.Parent; -import com.kidsqueue.kidsqueue.parent.db.ParentRepository; -import com.kidsqueue.kidsqueue.review.db.ReviewRepository; -import com.kidsqueue.kidsqueue.review.dtos.ReviewCreateDto; -import com.kidsqueue.kidsqueue.review.dtos.ReviewReadDto; -import com.kidsqueue.kidsqueue.review.dtos.ReviewUpdateDto; -import com.kidsqueue.kidsqueue.review.model.Review; -import jakarta.transaction.Transactional; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.data.domain.PageRequest; - -import java.util.List; -import java.util.Optional; - -import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; -import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; -import static org.junit.jupiter.api.Assertions.*; - -@SpringBootTest -@Transactional -class ReviewServiceTest { - - @Autowired ReviewService reviewService; - @Autowired HospitalRepository hospitalRepository; - @Autowired ParentRepository parentRepository; - @Autowired - ReviewRepository reviewRepository; - - - // TODO : 리팩터링 반영되지 않은 코드, 참고 불가함 - - @BeforeEach - void setUp() { - Hospital hospital1 = generateHospital("병원1", "000-0000-0001"); - Hospital hospital2 = generateHospital("병원2", "000-0000-0002"); - - Parent parent1 = generateParent("testSignUp1", "010-0000-0001", "0000000000000", "testSignUp@naver.com"); - Parent parent2 = generateParent("testSignUp2", "010-0000-0002", "0000000000001", "testSignUp2@naver.com"); - - generateReview("리뷰1", hospital1, parent1); - generateReview("리뷰2", hospital2, parent2); - } - - @Test - @DisplayName("리뷰를 오름차순 정렬한다.") - void findAllAsc() { - PageRequest pageRequest = PageRequest.of(0, 10); - - List list = reviewService.findAllAsc(pageRequest).getData(); - - assertTrue((list.get(0).getCreatedBy().isBefore(list.get(1).getCreatedBy()))); - } - - @Test - @DisplayName("리뷰를 내림차순 정렬한다.") - void findAllDesc() { - PageRequest pageRequest = PageRequest.of(0, 10); - - List list = reviewService.findAllDesc(pageRequest).getData(); - - assertTrue((list.get(0).getCreatedBy().isAfter(list.get(1).getCreatedBy()))); - } - - - // TODO : given 조건으로 ID 리터럴을 준비하는 법, 아직 생각 못 했음 - - @Test - @DisplayName("리뷰 생성에 실패한다. - hospital id 조회 실패") - void createReview_negativeCase_notFound_hospitalId() { - } - - - @Test - @DisplayName("리뷰 생성에 실패한다. - parent id 조회 실패") - void createReview_negativeCase_notFound_parentId() { - - } - - @Test - @DisplayName("리뷰 생성에 성공한다.") - void createReview_positiveCase() { - // TODO : given 이 너무 무겁지만 API 스펙을 변경하지 않는 선에서 auto increment 되는 ID를 어떻게 특정할지 모르겠음 - int prevSize = reviewRepository.findAll().size(); - Long hospitalId = hospitalRepository.findAll().get(0).getId(); - Long parentId = parentRepository.findAll().get(0).getId(); - ReviewCreateDto reviewCreateDto = ReviewCreateDto.builder() - .title("리뷰3") - .description("설명3") - .score(5) - .parentId(parentId) - .hospitalId(hospitalId) - .build(); - - Api apiResponse = reviewService.createReview(reviewCreateDto); - - assertEquals("리뷰 정보 생성 성공", apiResponse.getMessage()); - assertEquals(prevSize + 1, reviewRepository.findAll().size()); - } - - @Test - @DisplayName("리뷰를 업데이트한다.") - void updateReview() { - Long id = reviewRepository.findAll().get(0).getId(); - ReviewUpdateDto reviewUpdateDto = ReviewUpdateDto.builder() - .title("리뷰 수정1") - .description("설명 수정1") - .score(1) - .build(); - - Api apiResponse = reviewService.updateReview(id, reviewUpdateDto); - - assertEquals("리뷰 정보 수정 성공", apiResponse.getMessage()); - assertEquals("리뷰 수정1", reviewService.findReviewById(id).getData().getTitle()); - } - - @Test - @DisplayName("리뷰를 삭제한다.") - void deleteReview() { - Long id = reviewRepository.findAll().get(0).getId(); - - reviewService.deleteReview(id); - - Optional reviewOptional = reviewRepository.findById(id); - if (reviewOptional.isPresent()) - assertEquals(0, reviewOptional.get().getIsActive()); - else fail("deleteReview 메서드는 삭제되는 대신 isActive 가 변경돼야 합니다."); - } - - Hospital generateHospital(String name, String phoneNumber) { - Hospital hospital = Hospital.builder() - .name(name) - .address(name + "주소") - .description(name + "설명") - .phoneNumber(phoneNumber) - .maxNumOfPeople(5) - .status(Status.OPEN) - .build(); - hospitalRepository.save(hospital); - - return hospital; - } - - Parent generateParent(String loginId, String phoneNumber, String residentRegistrationNumber, String email) { - Parent parent = Parent.builder() - .loginId(loginId) - .password("비밀번호") - .nickname(loginId + "별명") - .name("이름") - .age("20") - .gender(남) - .phoneNumber(phoneNumber) - .residentRegistrationNumber(residentRegistrationNumber) - .email(email) - .role(USER) - .build(); - parentRepository.save(parent); - return parent; - } - - void generateReview(String title, Hospital hospital, Parent parent) { - Review review = Review.builder() - .title(title) - .score(5) - .description(title + "설명") - .hospital(hospital) - .parent(parent) - .build(); - reviewRepository.save(review); - } -} \ No newline at end of file +public class ReviewServiceTest { +} From 0aff0aa3db3ca08bf6e828c9ad369b18fc377249 Mon Sep 17 00:00:00 2001 From: dfdrdodm95 Date: Tue, 11 Jun 2024 21:17:09 +0900 Subject: [PATCH 9/9] =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=9D=BC=EB=B6=80=20=EC=86=8C=ED=98=95=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../review/model/ReviewUpdateResponse.java | 2 + .../service}/ReviewServiceTest.java | 66 ++++----- .../review/service/ReviewServiceTest.java | 136 ++++++++++++++++++ 4 files changed, 172 insertions(+), 33 deletions(-) rename src/test/java/com/kidsqueue/kidsqueue/medium/{ => review/service}/ReviewServiceTest.java (94%) diff --git a/build.gradle b/build.gradle index f6282a4..b49e966 100644 --- a/build.gradle +++ b/build.gradle @@ -77,6 +77,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.security:spring-security-oauth2-client' + testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.0' } diff --git a/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateResponse.java b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateResponse.java index 09f333d..ef14b8e 100644 --- a/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateResponse.java +++ b/src/main/java/com/kidsqueue/kidsqueue/review/model/ReviewUpdateResponse.java @@ -4,8 +4,10 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import lombok.Builder; +import lombok.Getter; import org.springframework.util.Assert; +@Getter public class ReviewUpdateResponse { @NotBlank private final String title; diff --git a/src/test/java/com/kidsqueue/kidsqueue/medium/ReviewServiceTest.java b/src/test/java/com/kidsqueue/kidsqueue/medium/review/service/ReviewServiceTest.java similarity index 94% rename from src/test/java/com/kidsqueue/kidsqueue/medium/ReviewServiceTest.java rename to src/test/java/com/kidsqueue/kidsqueue/medium/review/service/ReviewServiceTest.java index 71366c7..c91a344 100644 --- a/src/test/java/com/kidsqueue/kidsqueue/medium/ReviewServiceTest.java +++ b/src/test/java/com/kidsqueue/kidsqueue/medium/review/service/ReviewServiceTest.java @@ -1,4 +1,4 @@ -package com.kidsqueue.kidsqueue.medium; +package com.kidsqueue.kidsqueue.medium.review.service; import com.kidsqueue.kidsqueue.common.Api; import com.kidsqueue.kidsqueue.hospital.db.Hospital; @@ -26,6 +26,7 @@ import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; +import static org.assertj.core.api.Assertions.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -51,32 +52,16 @@ void setUp() { parent = createParent("testSignUp1", "010-0000-0001", "0000000000000", "testSignUp@naver.com"); } + // 메서드 시그너쳐 상 동일성 비교가 불가능하므로 repository 테스트로 이를 대체하고 반환값만 검증하였음 + // 테스트 DB가 계속 비어있다는 가정이면, 전체 조회를 2회 시행해서 전후를 비교하고 괜찮은 보호 수준을 확보해도 문제 없을 것. @Test - @DisplayName("리뷰를 오름차순 정렬한다.") - void findAllAsc() { - Review review1 = createReview("리뷰 1", hospital, parent); - Review review2 = createReview("리뷰 2", hospital, parent); - reviewRepository.save(review1); - reviewRepository.save(review2); - PageRequest pageRequest = PageRequest.of(0, 10); - - List list = reviewService.findAllAsc(pageRequest).getData(); - - assertTrue((list.get(list.size() - 2).getCreatedBy().isBefore(list.get(list.size() - 1).getCreatedBy()))); - } - - @Test - @DisplayName("리뷰를 내림차순 정렬한다.") - void findAllDesc() { - Review review1 = createReview("리뷰 1", hospital, parent); - Review review2 = createReview("리뷰 2", hospital, parent); - reviewRepository.save(review1); - reviewRepository.save(review2); - PageRequest pageRequest = PageRequest.of(0, 10); + @DisplayName("리뷰 생성에 성공한다.") + void createReview_positiveCase() { + ReviewCreateRequest request = createReviewCreateRequest("리뷰 1", hospital, parent); - List list = reviewService.findAllDesc(pageRequest).getData(); + Api apiResponse = reviewService.createReview(request); - assertTrue((list.get(list.size() - 2).getCreatedBy().isAfter(list.get(list.size() - 1).getCreatedBy()))); + assertThat(apiResponse.getData().getTitle()).isEqualTo(request.getTitle()); } @Test @@ -94,7 +79,6 @@ void createReview_negativeCase_notFound_hospitalId() { .hasMessageContaining(ReviewErrorCode.Hospital_Not_Found.getDescription()); } - @Test @DisplayName("리뷰 생성에 실패한다. - parent id 조회 실패") void createReview_negativeCase_notFound_parentId() { @@ -110,16 +94,32 @@ void createReview_negativeCase_notFound_parentId() { .hasMessageContaining(ReviewErrorCode.Parent_Not_Found.getDescription()); } - // 메서드 시그너쳐 상 동일성 비교가 불가능하므로 repository 테스트로 이를 대체하고 반환값만 검증하였음 - // 테스트 DB가 계속 비어있다는 가정이면, 전체 조회를 2회 시행해서 전후를 비교하고 괜찮은 보호 수준을 확보해도 문제 없을 것. @Test - @DisplayName("리뷰 생성에 성공한다.") - void createReview_positiveCase() { - ReviewCreateRequest request = createReviewCreateRequest("리뷰 1", hospital, parent); + @DisplayName("리뷰를 오름차순 정렬한다.") + void findAllAsc() { + Review review1 = createReview("리뷰 1", hospital, parent); + Review review2 = createReview("리뷰 2", hospital, parent); + reviewRepository.save(review1); + reviewRepository.save(review2); + PageRequest pageRequest = PageRequest.of(0, 10); - Api apiResponse = reviewService.createReview(request); + List list = reviewService.findAllAsc(pageRequest).getData(); - Assertions.assertThat(apiResponse.getData().getTitle()).isEqualTo(request.getTitle()); + assertTrue((list.get(list.size() - 2).getCreatedBy().isBefore(list.get(list.size() - 1).getCreatedBy()))); + } + + @Test + @DisplayName("리뷰를 내림차순 정렬한다.") + void findAllDesc() { + Review review1 = createReview("리뷰 1", hospital, parent); + Review review2 = createReview("리뷰 2", hospital, parent); + reviewRepository.save(review1); + reviewRepository.save(review2); + PageRequest pageRequest = PageRequest.of(0, 10); + + List list = reviewService.findAllDesc(pageRequest).getData(); + + assertTrue((list.get(list.size() - 2).getCreatedBy().isAfter(list.get(list.size() - 1).getCreatedBy()))); } @Test @@ -149,7 +149,7 @@ void deleteReview() { Optional reviewOptional = reviewRepository.findById(review.getId()); if (reviewOptional.isPresent()) assertEquals(0, reviewOptional.get().getIsActive()); - else Assertions.fail("deleteReview 메서드는 삭제되는 대신 isActive 가 변경돼야 합니다."); + else fail("deleteReview 메서드는 삭제되는 대신 isActive 가 변경돼야 합니다."); } Hospital createHospital(String name, String phoneNumber) { diff --git a/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java b/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java index 02a6b35..d2ea644 100644 --- a/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java +++ b/src/test/java/com/kidsqueue/kidsqueue/review/service/ReviewServiceTest.java @@ -1,4 +1,140 @@ package com.kidsqueue.kidsqueue.review.service; +import com.kidsqueue.kidsqueue.common.Api; +import com.kidsqueue.kidsqueue.hospital.db.Hospital; +import com.kidsqueue.kidsqueue.hospital.db.HospitalRepository; +import com.kidsqueue.kidsqueue.hospital.db.enums.Status; +import com.kidsqueue.kidsqueue.parent.db.Parent; +import com.kidsqueue.kidsqueue.parent.db.ParentRepository; +import com.kidsqueue.kidsqueue.review.db.Review; +import com.kidsqueue.kidsqueue.review.db.ReviewRepository; +import com.kidsqueue.kidsqueue.review.model.ReviewCreateRequest; +import com.kidsqueue.kidsqueue.review.model.ReviewCreateResponse; +import com.kidsqueue.kidsqueue.review.model.ReviewUpdateRequest; +import com.kidsqueue.kidsqueue.review.model.ReviewUpdateResponse; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; + +import static com.kidsqueue.kidsqueue.parent.db.enums.Gender.남; +import static com.kidsqueue.kidsqueue.parent.db.enums.RoleType.USER; +import static org.assertj.core.api.BDDAssertions.then; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) public class ReviewServiceTest { + + @InjectMocks ReviewService reviewService; + @Mock private ReviewRepository reviewRepository; + @Mock private HospitalRepository hospitalRepository; + @Mock private ParentRepository parentRepository; + private Hospital hospital; + private Parent parent; + + @BeforeEach + void setUp() { + hospital = spy(createHospital("병원1", "000-0000-0001")); + parent = spy(createParent("testSignUp1", "010-0000-0001", "0000000000000", "testSignUp@naver.com")); + Mockito.when(reviewRepository.save(any(Review.class))).thenAnswer(invocation -> { + return invocation.getArgument(0); + }); + } + + // ToDto, fromEntity 등 POJO 메서드들에 대한 테스트 추가해야 함 + // 메서드는 객체 간 협력을 검사하는 역할만 수행하고 있다. + @Test + void 리뷰_생성에_성공한다() { + doReturn(1L).when(hospital).getId(); + doReturn(1L).when(parent).getId(); + Mockito.when(hospitalRepository.findById(any(Long.class))).thenReturn(Optional.ofNullable(hospital)); + Mockito.when(parentRepository.findById(any(Long.class))).thenReturn(Optional.ofNullable(parent)); + ReviewCreateRequest request = createReviewCreateRequest("리뷰 1", hospital, parent); + + Api response = reviewService.createReview(request); + + then(response.getData().getTitle()).isEqualTo(request.getTitle()); + } + + // TODO : 외부 의존성을 끊고 나면 스스로 검사하는 항목이 없는 거 같아 고민 중 + @Disabled // 활성화하면 BeforeEach의 save stubbing 때문에 컴파일 에러가 발생함 + @Test + @DisplayName("리뷰를 오름차순 정렬한다.") + void findAllAsc() { + } + + @Test + void 리뷰를_업데이트_한다() { + Review review = spy(createReview("리뷰 1", hospital, parent)); + doReturn(1L).when(review).getId(); + Mockito.when(reviewRepository.findById(any(Long.class))).thenReturn(Optional.ofNullable(review)); + ReviewUpdateRequest request = createReviewUpdateRequest("수정 1"); + + Api response = reviewService.updateReview(review.getId(), request); + + then(response.getData().getTitle()).isEqualTo(request.getTitle()); + } + Hospital createHospital(String name, String phoneNumber) { + Hospital hospital = Hospital.builder() + .name(name) + .address(name + "주소") + .description(name + "설명") + .phoneNumber(phoneNumber) + .maxNumOfPeople(5) + .status(Status.OPEN) + .build(); + return hospital; + } + + Parent createParent(String loginId, String phoneNumber, String residentRegistrationNumber, String email) { + Parent parent = Parent.builder() + .loginId(loginId) + .password("비밀번호") + .nickname(loginId + "별명") + .name("이름") + .age("20") + .gender(남) + .phoneNumber(phoneNumber) + .residentRegistrationNumber(residentRegistrationNumber) + .email(email) + .role(USER) + .build(); + return parent; + } + + Review createReview(String title, Hospital hospital, Parent parent) { + return Review.builder() + .title(title) + .score(5) + .description(title + "설명") + .hospital(hospital) + .parent(parent) + .isActive(1) + .build(); + } + + ReviewCreateRequest createReviewCreateRequest(String title, Hospital hospital, Parent parent) { + return ReviewCreateRequest.builder() + .title(title) + .score(5) + .description(title + " 설명") + .parentId(parent.getId()) + .hospitalId(hospital.getId()) + .build(); + } + + ReviewUpdateRequest createReviewUpdateRequest(String title) { + return ReviewUpdateRequest.builder() + .title(title) + .score(5) + .description(title + " 설명") + .build(); + } }