From 1a8b3d8ee30f3121825de48b0ef913182d901856 Mon Sep 17 00:00:00 2001 From: nuyh Date: Thu, 20 Jul 2023 17:58:20 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=B6=94=EC=B2=9C=20=ED=8F=AC=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=93=B1=EB=A1=9D,=20=EC=88=98=EC=A0=95,=20?= =?UTF-8?q?=EC=82=AD=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit #1397 --- .../application/RecommendedService.java | 59 ++++++++++++ .../application/dto/RecommendedRequest.java | 14 +++ .../dto/RecommendedUpdateRequest.java | 14 +++ .../repository/RecommendedRepository.java | 7 ++ .../RecommendedPostNotFoundException.java | 6 ++ .../application/RecommendedServiceTest.java | 93 +++++++++++++++++++ 6 files changed, 193 insertions(+) create mode 100644 backend/src/main/java/wooteco/prolog/roadmap/application/RecommendedService.java create mode 100644 backend/src/main/java/wooteco/prolog/roadmap/application/dto/RecommendedRequest.java create mode 100644 backend/src/main/java/wooteco/prolog/roadmap/application/dto/RecommendedUpdateRequest.java create mode 100644 backend/src/main/java/wooteco/prolog/roadmap/domain/repository/RecommendedRepository.java create mode 100644 backend/src/main/java/wooteco/prolog/roadmap/exception/RecommendedPostNotFoundException.java create mode 100644 backend/src/test/java/wooteco/prolog/roadmap/application/RecommendedServiceTest.java diff --git a/backend/src/main/java/wooteco/prolog/roadmap/application/RecommendedService.java b/backend/src/main/java/wooteco/prolog/roadmap/application/RecommendedService.java new file mode 100644 index 000000000..cd8134a77 --- /dev/null +++ b/backend/src/main/java/wooteco/prolog/roadmap/application/RecommendedService.java @@ -0,0 +1,59 @@ +package wooteco.prolog.roadmap.application; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import wooteco.prolog.roadmap.application.dto.RecommendedRequest; +import wooteco.prolog.roadmap.application.dto.RecommendedUpdateRequest; +import wooteco.prolog.roadmap.domain.Keyword; +import wooteco.prolog.roadmap.domain.RecommendedPost; +import wooteco.prolog.roadmap.domain.repository.KeywordRepository; +import wooteco.prolog.roadmap.domain.repository.RecommendedRepository; +import wooteco.prolog.roadmap.exception.KeywordNotFoundException; +import wooteco.prolog.roadmap.exception.RecommendedPostNotFoundException; + +@Transactional(readOnly = true) +@Service +public class RecommendedService { + + private final RecommendedRepository recommendedRepository; + private final KeywordRepository keywordRepository; + + public RecommendedService(final RecommendedRepository recommendedRepository, final KeywordRepository keywordRepository) { + this.recommendedRepository = recommendedRepository; + this.keywordRepository = keywordRepository; + } + + @Transactional + public Long create(final Long keywordId, final RecommendedRequest request) { + final Keyword keyword = findKeywordOrThrow(keywordId); + + final RecommendedPost post = new RecommendedPost(request.getUrl()); + post.addKeyword(keyword); + + return recommendedRepository.save(post).getId(); + } + + private Keyword findKeywordOrThrow(final Long keywordId) { + return keywordRepository.findById(keywordId) + .orElseThrow(KeywordNotFoundException::new); + } + + @Transactional + public void update(final Long recommendedId, final RecommendedUpdateRequest request) { + final RecommendedPost post = findPostOrThrow(recommendedId); + + post.updateUrl(request.getUrl()); + } + + private RecommendedPost findPostOrThrow(final Long recommendedId) { + return recommendedRepository.findById(recommendedId) + .orElseThrow(RecommendedPostNotFoundException::new); + } + + @Transactional + public void delete(final Long recommendedId) { + final RecommendedPost recommendedPost = findPostOrThrow(recommendedId); + recommendedPost.remove(); + recommendedRepository.delete(recommendedPost); + } +} diff --git a/backend/src/main/java/wooteco/prolog/roadmap/application/dto/RecommendedRequest.java b/backend/src/main/java/wooteco/prolog/roadmap/application/dto/RecommendedRequest.java new file mode 100644 index 000000000..a515dfb65 --- /dev/null +++ b/backend/src/main/java/wooteco/prolog/roadmap/application/dto/RecommendedRequest.java @@ -0,0 +1,14 @@ +package wooteco.prolog.roadmap.application.dto; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class RecommendedRequest { + + private String url; +} diff --git a/backend/src/main/java/wooteco/prolog/roadmap/application/dto/RecommendedUpdateRequest.java b/backend/src/main/java/wooteco/prolog/roadmap/application/dto/RecommendedUpdateRequest.java new file mode 100644 index 000000000..44b2db78f --- /dev/null +++ b/backend/src/main/java/wooteco/prolog/roadmap/application/dto/RecommendedUpdateRequest.java @@ -0,0 +1,14 @@ +package wooteco.prolog.roadmap.application.dto; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class RecommendedUpdateRequest { + + private String url; +} diff --git a/backend/src/main/java/wooteco/prolog/roadmap/domain/repository/RecommendedRepository.java b/backend/src/main/java/wooteco/prolog/roadmap/domain/repository/RecommendedRepository.java new file mode 100644 index 000000000..5bb66066e --- /dev/null +++ b/backend/src/main/java/wooteco/prolog/roadmap/domain/repository/RecommendedRepository.java @@ -0,0 +1,7 @@ +package wooteco.prolog.roadmap.domain.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import wooteco.prolog.roadmap.domain.RecommendedPost; + +public interface RecommendedRepository extends JpaRepository { +} diff --git a/backend/src/main/java/wooteco/prolog/roadmap/exception/RecommendedPostNotFoundException.java b/backend/src/main/java/wooteco/prolog/roadmap/exception/RecommendedPostNotFoundException.java new file mode 100644 index 000000000..57a336794 --- /dev/null +++ b/backend/src/main/java/wooteco/prolog/roadmap/exception/RecommendedPostNotFoundException.java @@ -0,0 +1,6 @@ +package wooteco.prolog.roadmap.exception; + +import wooteco.prolog.common.exception.BadRequestException; + +public class RecommendedPostNotFoundException extends BadRequestException { +} diff --git a/backend/src/test/java/wooteco/prolog/roadmap/application/RecommendedServiceTest.java b/backend/src/test/java/wooteco/prolog/roadmap/application/RecommendedServiceTest.java new file mode 100644 index 000000000..ef10a52d2 --- /dev/null +++ b/backend/src/test/java/wooteco/prolog/roadmap/application/RecommendedServiceTest.java @@ -0,0 +1,93 @@ +package wooteco.prolog.roadmap.application; + +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.transaction.annotation.Transactional; +import wooteco.prolog.roadmap.application.dto.RecommendedRequest; +import wooteco.prolog.roadmap.application.dto.RecommendedUpdateRequest; +import wooteco.prolog.roadmap.domain.Keyword; +import wooteco.prolog.roadmap.domain.RecommendedPost; +import wooteco.prolog.roadmap.domain.repository.KeywordRepository; +import wooteco.prolog.roadmap.domain.repository.RecommendedRepository; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.SoftAssertions.assertSoftly; + +@SpringBootTest +@Transactional +class RecommendedServiceTest { + + @Autowired + private RecommendedService recommendedService; + @Autowired + private RecommendedRepository recommendedRepository; + @Autowired + private KeywordRepository keywordRepository; + + private Keyword keyword; + + @BeforeEach + public void init() { + final Keyword keyword = Keyword.createKeyword("이름", "설명", 1, 1, 1L, null); + this.keyword = keywordRepository.save(keyword); + } + + @Test + @DisplayName("추천 포스트 생성 테스트") + void create() { + //given + final RecommendedRequest request = new RecommendedRequest("https//:example.com"); + + //when + Long recommendedPostId = recommendedService.create(keyword.getId(), request); + + final Keyword persistedKeyword = keywordRepository.findById(keyword.getId()).get(); + final RecommendedPost persistedPost = recommendedRepository.findById(recommendedPostId).get(); + + //then + assertSoftly(softAssertions -> { + assertThat(persistedPost.getUrl()).isEqualTo(request.getUrl()); + assertThat(persistedKeyword.getRecommendedPosts()).containsExactly(persistedPost); + }); + } + + @Test + @DisplayName("추천 포스트 수정 테스트") + void update() { + //given + final RecommendedRequest request = new RecommendedRequest("https//:example.com"); + Long recommendedPostId = recommendedService.create(keyword.getId(), request); + String newUrl = "https//:example222.com"; + final RecommendedUpdateRequest updateRrequest = new RecommendedUpdateRequest(newUrl); + + //when + recommendedService.update(recommendedPostId, updateRrequest); + Optional actual = recommendedRepository.findById(recommendedPostId); + + //then + assertThat(actual.get().getUrl()).isEqualTo(newUrl); + } + + @Test + @DisplayName("추천 포스트 삭제 테스트") + void delete() { + //given + final RecommendedRequest request = new RecommendedRequest("https//:example.com"); + Long recommendedPostId = recommendedService.create(keyword.getId(), request); + + //when + recommendedService.delete(recommendedPostId); + + //then + assertSoftly(softAssertions -> { + assertThat(recommendedRepository.findAll()).hasSize(0); + assertThat(keywordRepository.findById(keyword.getId()).get().getRecommendedPosts()) + .isEmpty(); + }); + } +}