From b24cb11b0ab861fa4ac479ba00018e2c0c81b84e Mon Sep 17 00:00:00 2001 From: jiholee0 Date: Sat, 24 Feb 2024 23:58:12 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20=EC=84=9C=EB=B9=84=EC=8A=A4=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/ReportPlaceControllerV1.java | 12 +- ...Response.java => ReportPlaceResponse.java} | 6 +- .../service/ReportPlaceQueryService.java | 8 +- .../api/ReportPlaceControllerV1Test.java | 2 +- .../ReportPlaceCommandServiceTest.java | 139 ++++++++++++++++++ .../service/ReportPlaceQueryServiceTest.java | 123 ++++++++++++++++ 6 files changed, 276 insertions(+), 14 deletions(-) rename src/main/java/com/zelusik/eatery/domain/report_place/dto/response/{PostReportPlaceResponse.java => ReportPlaceResponse.java} (88%) create mode 100644 src/test/java/com/zelusik/eatery/unit/domain/report_place/service/ReportPlaceCommandServiceTest.java create mode 100644 src/test/java/com/zelusik/eatery/unit/domain/report_place/service/ReportPlaceQueryServiceTest.java diff --git a/src/main/java/com/zelusik/eatery/domain/report_place/api/ReportPlaceControllerV1.java b/src/main/java/com/zelusik/eatery/domain/report_place/api/ReportPlaceControllerV1.java index 9030c7d..d67d475 100644 --- a/src/main/java/com/zelusik/eatery/domain/report_place/api/ReportPlaceControllerV1.java +++ b/src/main/java/com/zelusik/eatery/domain/report_place/api/ReportPlaceControllerV1.java @@ -2,7 +2,7 @@ import com.zelusik.eatery.domain.report_place.dto.ReportPlaceDto; import com.zelusik.eatery.domain.report_place.dto.request.ReportPlaceRequest; -import com.zelusik.eatery.domain.report_place.dto.response.PostReportPlaceResponse; +import com.zelusik.eatery.domain.report_place.dto.response.ReportPlaceResponse; import com.zelusik.eatery.domain.report_place.service.ReportPlaceCommandService; import com.zelusik.eatery.domain.report_place.service.ReportPlaceQueryService; import com.zelusik.eatery.global.auth.UserPrincipal; @@ -38,13 +38,13 @@ public class ReportPlaceControllerV1 { security = @SecurityRequirement(name = "access-token") ) @PostMapping(headers = API_MINOR_VERSION_HEADER_NAME + "=1") - public ResponseEntity reportPlaceV1( + public ResponseEntity reportPlaceV1( @AuthenticationPrincipal UserPrincipal userPrincipal, @RequestBody @Valid ReportPlaceRequest reportPlaceRequest) { ReportPlaceDto reportPlaceDto = reportPlaceCommandService.reportPlace(userPrincipal.getMemberId(), reportPlaceRequest); return ResponseEntity .created(URI.create("/api/v1/reports/places/" + reportPlaceDto.getId())) - .body(PostReportPlaceResponse.from(reportPlaceDto)); + .body(ReportPlaceResponse.from(reportPlaceDto)); } @Operation(summary = "장소 신고 내역(정보 수정 제안) 단건 조회", @@ -53,13 +53,13 @@ public ResponseEntity reportPlaceV1( security = @SecurityRequirement(name = "access-token") ) @GetMapping(value = "/{reportPlaceId}", headers = API_MINOR_VERSION_HEADER_NAME + "=1") - public PostReportPlaceResponse findReportPlaceByIdV1( + public ReportPlaceResponse findReportPlaceByIdV1( @Parameter( description = "PK of reportPlace", example = "3" ) @PathVariable Long reportPlaceId ) { - ReportPlaceDto reportPlaceDto = reportPlaceQueryService.getDtoByReportPlaceId(reportPlaceId); - return PostReportPlaceResponse.from(reportPlaceDto); + ReportPlaceDto reportPlaceDto = reportPlaceQueryService.getDtoById(reportPlaceId); + return ReportPlaceResponse.from(reportPlaceDto); } } \ No newline at end of file diff --git a/src/main/java/com/zelusik/eatery/domain/report_place/dto/response/PostReportPlaceResponse.java b/src/main/java/com/zelusik/eatery/domain/report_place/dto/response/ReportPlaceResponse.java similarity index 88% rename from src/main/java/com/zelusik/eatery/domain/report_place/dto/response/PostReportPlaceResponse.java rename to src/main/java/com/zelusik/eatery/domain/report_place/dto/response/ReportPlaceResponse.java index 9fa5bc0..42cbc17 100644 --- a/src/main/java/com/zelusik/eatery/domain/report_place/dto/response/PostReportPlaceResponse.java +++ b/src/main/java/com/zelusik/eatery/domain/report_place/dto/response/ReportPlaceResponse.java @@ -10,7 +10,7 @@ @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PRIVATE) @Getter -public class PostReportPlaceResponse { +public class ReportPlaceResponse { @Schema(description = "장소 신고의 id(PK)", example = "19") private Long id; @@ -27,8 +27,8 @@ public class PostReportPlaceResponse { @Schema(description = "신고 이유 상세", example = "전화번호가 ~~로 변경되었습니다.") private String reasonDetail; - public static PostReportPlaceResponse from(ReportPlaceDto reportPlaceDto) { - return new PostReportPlaceResponse( + public static ReportPlaceResponse from(ReportPlaceDto reportPlaceDto) { + return new ReportPlaceResponse( reportPlaceDto.getId(), reportPlaceDto.getReporterId(), reportPlaceDto.getPlace().getId(), diff --git a/src/main/java/com/zelusik/eatery/domain/report_place/service/ReportPlaceQueryService.java b/src/main/java/com/zelusik/eatery/domain/report_place/service/ReportPlaceQueryService.java index d227d55..163cc80 100644 --- a/src/main/java/com/zelusik/eatery/domain/report_place/service/ReportPlaceQueryService.java +++ b/src/main/java/com/zelusik/eatery/domain/report_place/service/ReportPlaceQueryService.java @@ -18,12 +18,12 @@ public class ReportPlaceQueryService { /** * reportPlaceId에 해당하는 장소 신고 내역을 조회한다. * - * @param reportPlaceId 조회하고자 하는 장소 신고 내역의 PK + * @param id 조회하고자 하는 장소 신고 내역의 PK * @return 조회된 장소 신고 내역의 dto */ - public ReportPlaceDto getDtoByReportPlaceId(Long reportPlaceId) { - ReportPlace reportPlace = reportPlaceRepository.findById(reportPlaceId) - .orElseThrow(() -> new ReportPlaceNotFoundByIdException(reportPlaceId)); + public ReportPlaceDto getDtoById(Long id) { + ReportPlace reportPlace = reportPlaceRepository.findById(id) + .orElseThrow(() -> new ReportPlaceNotFoundByIdException(id)); return ReportPlaceDto.from(reportPlace); } } diff --git a/src/test/java/com/zelusik/eatery/unit/domain/report_place/api/ReportPlaceControllerV1Test.java b/src/test/java/com/zelusik/eatery/unit/domain/report_place/api/ReportPlaceControllerV1Test.java index ad66569..6ea6e65 100644 --- a/src/test/java/com/zelusik/eatery/unit/domain/report_place/api/ReportPlaceControllerV1Test.java +++ b/src/test/java/com/zelusik/eatery/unit/domain/report_place/api/ReportPlaceControllerV1Test.java @@ -108,7 +108,7 @@ void given_whenFindingReportPlaceWithId_thenReturnReportPlace() throws Exception String reasonDetail = "전화번호가 ~~로 수정되었어요."; ReportPlaceDto expectedResult = createReportPlaceDto(1L, reporterId, createPlaceDto(placeId), reasonOption, reasonDetail); - given(reportPlaceQueryService.getDtoByReportPlaceId(id)).willReturn(expectedResult); + given(reportPlaceQueryService.getDtoById(id)).willReturn(expectedResult); // when & then mvc.perform( diff --git a/src/test/java/com/zelusik/eatery/unit/domain/report_place/service/ReportPlaceCommandServiceTest.java b/src/test/java/com/zelusik/eatery/unit/domain/report_place/service/ReportPlaceCommandServiceTest.java new file mode 100644 index 0000000..852e5cf --- /dev/null +++ b/src/test/java/com/zelusik/eatery/unit/domain/report_place/service/ReportPlaceCommandServiceTest.java @@ -0,0 +1,139 @@ +package com.zelusik.eatery.unit.domain.report_place.service; + +import com.zelusik.eatery.domain.member.constant.Gender; +import com.zelusik.eatery.domain.member.constant.LoginType; +import com.zelusik.eatery.domain.member.constant.RoleType; +import com.zelusik.eatery.domain.member.entity.Member; +import com.zelusik.eatery.domain.member.service.MemberQueryService; +import com.zelusik.eatery.domain.place.constant.KakaoCategoryGroupCode; +import com.zelusik.eatery.domain.place.entity.Address; +import com.zelusik.eatery.domain.place.entity.Place; +import com.zelusik.eatery.domain.place.entity.PlaceCategory; +import com.zelusik.eatery.domain.place.entity.Point; +import com.zelusik.eatery.domain.place.service.PlaceQueryService; +import com.zelusik.eatery.domain.report_place.dto.ReportPlaceDto; +import com.zelusik.eatery.domain.report_place.dto.ReportPlaceReasonOption; +import com.zelusik.eatery.domain.report_place.dto.request.ReportPlaceRequest; +import com.zelusik.eatery.domain.report_place.entity.ReportPlace; +import com.zelusik.eatery.domain.report_place.repository.ReportPlaceRepository; +import com.zelusik.eatery.domain.report_place.service.ReportPlaceCommandService; +import com.zelusik.eatery.domain.review.constant.ReviewKeywordValue; +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.junit.jupiter.MockitoExtension; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; + +@DisplayName("[Unit] Service(Command) - Report place") +@ExtendWith(MockitoExtension.class) +class ReportPlaceCommandServiceTest { + + @InjectMocks + private ReportPlaceCommandService sut; + + @Mock + private MemberQueryService memberQueryService; + @Mock + private PlaceQueryService placeQueryService; + @Mock + private ReportPlaceRepository reportPlaceRepository; + + @DisplayName("신고자 id와 장소 id, 장소 신고 요청 이유가 주어지고, 주어진 장소를 신고한다.") + @Test + void givenReporterIdAndRequest_whenReportingPlace_thenSavesReportPlace() { + // given + long reporterId = 1L; + long placeId = 2L; + Member reporter = createMember(reporterId); + Place place = createPlace(placeId, "12345"); + ReportPlaceReasonOption reasonOption = ReportPlaceReasonOption.NUMBER; + String reasonDetail = "전화번호가 ~~로 수정되었어요."; + ReportPlace reportPlace = createReportPlace(3L, reporter, place, reasonOption, reasonDetail); + given(memberQueryService.getById(reporterId)).willReturn(reporter); + given(placeQueryService.getById(placeId)).willReturn(place); + given(reportPlaceRepository.save(any(ReportPlace.class))).willReturn(reportPlace); + + // when + ReportPlaceDto actualResult = sut.reportPlace(reporterId, new ReportPlaceRequest(placeId, reasonOption, reasonDetail)); + + // then + then(memberQueryService).should().getById(reporterId); + then(placeQueryService).should().getById(placeId); + then(reportPlaceRepository).should().save(any(ReportPlace.class)); + verifyEveryMocksShouldHaveNoMoreInteractions(); + assertThat(actualResult) + .hasFieldOrPropertyWithValue("reporterId", reporter.getId()) + .hasFieldOrPropertyWithValue("place.id", place.getId()); + } + + private void verifyEveryMocksShouldHaveNoMoreInteractions() { + then(memberQueryService).shouldHaveNoMoreInteractions(); + then(placeQueryService).shouldHaveNoMoreInteractions(); + then(reportPlaceRepository).shouldHaveNoMoreInteractions(); + } + + private Member createMember(Long memberId) { + return createMember(memberId, Set.of(RoleType.USER)); + } + + private Member createMember(Long memberId, Set roleTypes) { + return new Member( + memberId, + "profile image url", + "profile thunmbnail image url", + "social user id", + LoginType.KAKAO, + roleTypes, + "email", + "nickname", + LocalDate.of(2000, 1, 1), + 20, + Gender.MALE, + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + } + + private Place createPlace(long id, String kakaoPid) { + return Place.of( + id, + List.of(ReviewKeywordValue.FRESH), + kakaoPid, + "place name", + "page url", + KakaoCategoryGroupCode.FD6, + new PlaceCategory("한식", "냉면", null), + null, + new Address("sido", "sgg", "lot number address", "road address"), + null, + new Point("37.5595073462493", "126.921462488105"), + "", + LocalDateTime.now(), + LocalDateTime.now() + ); + } + + private ReportPlace createReportPlace(Long id, Member reporter, Place place, ReportPlaceReasonOption reasonOption, String reasonDetail) { + return ReportPlace.create( + id, + reporter, + place, + reasonOption, + reasonDetail, + LocalDateTime.now(), + LocalDateTime.now() + ); + } +} \ No newline at end of file diff --git a/src/test/java/com/zelusik/eatery/unit/domain/report_place/service/ReportPlaceQueryServiceTest.java b/src/test/java/com/zelusik/eatery/unit/domain/report_place/service/ReportPlaceQueryServiceTest.java new file mode 100644 index 0000000..c04505a --- /dev/null +++ b/src/test/java/com/zelusik/eatery/unit/domain/report_place/service/ReportPlaceQueryServiceTest.java @@ -0,0 +1,123 @@ +package com.zelusik.eatery.unit.domain.report_place.service; + +import com.zelusik.eatery.domain.member.constant.Gender; +import com.zelusik.eatery.domain.member.constant.LoginType; +import com.zelusik.eatery.domain.member.constant.RoleType; +import com.zelusik.eatery.domain.member.entity.Member; +import com.zelusik.eatery.domain.place.constant.KakaoCategoryGroupCode; +import com.zelusik.eatery.domain.place.entity.Address; +import com.zelusik.eatery.domain.place.entity.Place; +import com.zelusik.eatery.domain.place.entity.PlaceCategory; +import com.zelusik.eatery.domain.place.entity.Point; +import com.zelusik.eatery.domain.report_place.dto.ReportPlaceDto; +import com.zelusik.eatery.domain.report_place.dto.ReportPlaceReasonOption; +import com.zelusik.eatery.domain.report_place.entity.ReportPlace; +import com.zelusik.eatery.domain.report_place.repository.ReportPlaceRepository; +import com.zelusik.eatery.domain.report_place.service.ReportPlaceQueryService; +import com.zelusik.eatery.domain.review.constant.ReviewKeywordValue; +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.junit.jupiter.MockitoExtension; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; + +@DisplayName("[Unit] Service(Query) - Report place") +@ExtendWith(MockitoExtension.class) +class ReportPlaceQueryServiceTest { + + @InjectMocks + private ReportPlaceQueryService sut; + + @Mock + private ReportPlaceRepository reportPlaceRepository; + + @DisplayName("장소 신고 내역 id가 주어지고, 신고자 id, 장소 정보, 이유, 상세 이유를 조회한다.") + @Test + void given_whenFindingReportPlaceWithId_thenReturnReportPlace() { + // given + long reporterId = 1L; + long placeId = 2L; + long reportPlaceId = 3L; + + ReportPlace expectedResult = createReportPlace(reportPlaceId, createMember(reporterId), createPlace(placeId, "12345"), ReportPlaceReasonOption.NUMBER, "전화번호가 ~~로 수정되었어요."); + given(reportPlaceRepository.findById(reportPlaceId)).willReturn(Optional.of(expectedResult)); + + // when + ReportPlaceDto actualResult = sut.getDtoById(reportPlaceId); + + // then + then(reportPlaceRepository).should().findById(reportPlaceId); + then(reportPlaceRepository).shouldHaveNoMoreInteractions(); + assertThat(actualResult) + .hasFieldOrPropertyWithValue("id", expectedResult.getId()) + .hasFieldOrPropertyWithValue("reporterId", expectedResult.getReporter().getId()) + .hasFieldOrPropertyWithValue("place.id", expectedResult.getPlace().getId()) + .hasFieldOrPropertyWithValue("reasonOption", expectedResult.getReasonOption()) + .hasFieldOrPropertyWithValue("reasonDetail", expectedResult.getReasonDetail()); + } + + private Member createMember(Long memberId) { + return createMember(memberId, Set.of(RoleType.USER)); + } + + private Member createMember(Long memberId, Set roleTypes) { + return new Member( + memberId, + "profile image url", + "profile thunmbnail image url", + "social user id", + LoginType.KAKAO, + roleTypes, + "email", + "nickname", + LocalDate.of(2000, 1, 1), + 20, + Gender.MALE, + LocalDateTime.now(), + LocalDateTime.now(), + null + ); + } + + private Place createPlace(long id, String kakaoPid) { + return Place.of( + id, + List.of(ReviewKeywordValue.FRESH), + kakaoPid, + "place name", + "page url", + KakaoCategoryGroupCode.FD6, + new PlaceCategory("한식", "냉면", null), + null, + new Address("sido", "sgg", "lot number address", "road address"), + null, + new Point("37.5595073462493", "126.921462488105"), + "", + LocalDateTime.now(), + LocalDateTime.now() + ); + } + + private ReportPlace createReportPlace(Long id, Member reporter, Place place, ReportPlaceReasonOption reasonOption, String reasonDetail) { + return ReportPlace.create( + id, + reporter, + place, + reasonOption, + reasonDetail, + LocalDateTime.now(), + LocalDateTime.now() + ); + } +} \ No newline at end of file