Skip to content

Commit f0edbca

Browse files
committed
feat: 추천 포스트 등록, 수정, 삭제 기능 추가
#1397
1 parent 583647b commit f0edbca

File tree

6 files changed

+193
-0
lines changed

6 files changed

+193
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package wooteco.prolog.roadmap.application;
2+
3+
import org.springframework.stereotype.Service;
4+
import org.springframework.transaction.annotation.Transactional;
5+
import wooteco.prolog.roadmap.application.dto.RecommendedRequest;
6+
import wooteco.prolog.roadmap.application.dto.RecommendedUpdateRequest;
7+
import wooteco.prolog.roadmap.domain.Keyword;
8+
import wooteco.prolog.roadmap.domain.RecommendedPost;
9+
import wooteco.prolog.roadmap.domain.repository.KeywordRepository;
10+
import wooteco.prolog.roadmap.domain.repository.RecommendedRepository;
11+
import wooteco.prolog.roadmap.exception.KeywordNotFoundException;
12+
import wooteco.prolog.roadmap.exception.RecommendedPostNotFoundException;
13+
14+
@Transactional(readOnly = true)
15+
@Service
16+
public class RecommendedService {
17+
18+
private final RecommendedRepository recommendedRepository;
19+
private final KeywordRepository keywordRepository;
20+
21+
public RecommendedService(final RecommendedRepository recommendedRepository, final KeywordRepository keywordRepository) {
22+
this.recommendedRepository = recommendedRepository;
23+
this.keywordRepository = keywordRepository;
24+
}
25+
26+
@Transactional
27+
public Long create(final Long keywordId, final RecommendedRequest request) {
28+
final Keyword keyword = findKeywordOrThrow(keywordId);
29+
30+
final RecommendedPost post = new RecommendedPost(request.getUrl());
31+
post.addKeyword(keyword);
32+
33+
return recommendedRepository.save(post).getId();
34+
}
35+
36+
private Keyword findKeywordOrThrow(final Long keywordId) {
37+
return keywordRepository.findById(keywordId)
38+
.orElseThrow(KeywordNotFoundException::new);
39+
}
40+
41+
@Transactional
42+
public void update(final Long recommendedId, final RecommendedUpdateRequest request) {
43+
final RecommendedPost post = findPostOrThrow(recommendedId);
44+
45+
post.updateUrl(request.getUrl());
46+
}
47+
48+
private RecommendedPost findPostOrThrow(final Long recommendedId) {
49+
return recommendedRepository.findById(recommendedId)
50+
.orElseThrow(RecommendedPostNotFoundException::new);
51+
}
52+
53+
@Transactional
54+
public void delete(final Long recommendedId) {
55+
final RecommendedPost recommendedPost = findPostOrThrow(recommendedId);
56+
recommendedPost.remove();
57+
recommendedRepository.delete(recommendedPost);
58+
}
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package wooteco.prolog.roadmap.application.dto;
2+
3+
import lombok.AccessLevel;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
8+
@Getter
9+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
10+
@AllArgsConstructor
11+
public class RecommendedRequest {
12+
13+
private String url;
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package wooteco.prolog.roadmap.application.dto;
2+
3+
import lombok.AccessLevel;
4+
import lombok.AllArgsConstructor;
5+
import lombok.Getter;
6+
import lombok.NoArgsConstructor;
7+
8+
@Getter
9+
@NoArgsConstructor(access = AccessLevel.PROTECTED)
10+
@AllArgsConstructor
11+
public class RecommendedUpdateRequest {
12+
13+
private String url;
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package wooteco.prolog.roadmap.domain.repository;
2+
3+
import org.springframework.data.jpa.repository.JpaRepository;
4+
import wooteco.prolog.roadmap.domain.RecommendedPost;
5+
6+
public interface RecommendedRepository extends JpaRepository<RecommendedPost, Long> {
7+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package wooteco.prolog.roadmap.exception;
2+
3+
import wooteco.prolog.common.exception.BadRequestException;
4+
5+
public class RecommendedPostNotFoundException extends BadRequestException {
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package wooteco.prolog.roadmap.application;
2+
3+
import org.junit.jupiter.api.BeforeEach;
4+
import org.junit.jupiter.api.DisplayName;
5+
import org.junit.jupiter.api.Test;
6+
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.boot.test.context.SpringBootTest;
8+
import org.springframework.transaction.annotation.Transactional;
9+
import wooteco.prolog.roadmap.application.dto.RecommendedRequest;
10+
import wooteco.prolog.roadmap.application.dto.RecommendedUpdateRequest;
11+
import wooteco.prolog.roadmap.domain.Keyword;
12+
import wooteco.prolog.roadmap.domain.RecommendedPost;
13+
import wooteco.prolog.roadmap.domain.repository.KeywordRepository;
14+
import wooteco.prolog.roadmap.domain.repository.RecommendedRepository;
15+
16+
import java.util.Optional;
17+
18+
import static org.assertj.core.api.Assertions.assertThat;
19+
import static org.assertj.core.api.SoftAssertions.assertSoftly;
20+
21+
@SpringBootTest
22+
@Transactional
23+
class RecommendedServiceTest {
24+
25+
@Autowired
26+
private RecommendedService recommendedService;
27+
@Autowired
28+
private RecommendedRepository recommendedRepository;
29+
@Autowired
30+
private KeywordRepository keywordRepository;
31+
32+
private Keyword keyword;
33+
34+
@BeforeEach
35+
public void init() {
36+
final Keyword keyword = Keyword.createKeyword("이름", "설명", 1, 1, 1L, null);
37+
this.keyword = keywordRepository.save(keyword);
38+
}
39+
40+
@Test
41+
@DisplayName("추천 포스트 생성 테스트")
42+
void create() {
43+
//given
44+
final RecommendedRequest request = new RecommendedRequest("https//:example.com");
45+
46+
//when
47+
Long recommendedPostId = recommendedService.create(keyword.getId(), request);
48+
49+
final Keyword persistedKeyword = keywordRepository.findById(keyword.getId()).get();
50+
final RecommendedPost persistedPost = recommendedRepository.findById(recommendedPostId).get();
51+
52+
//then
53+
assertSoftly(softAssertions -> {
54+
assertThat(persistedPost.getUrl()).isEqualTo(request.getUrl());
55+
assertThat(persistedKeyword.getRecommendedPosts()).containsExactly(persistedPost);
56+
});
57+
}
58+
59+
@Test
60+
@DisplayName("추천 포스트 수정 테스트")
61+
void update() {
62+
//given
63+
final RecommendedRequest request = new RecommendedRequest("https//:example.com");
64+
Long recommendedPostId = recommendedService.create(keyword.getId(), request);
65+
String newUrl = "https//:example222.com";
66+
final RecommendedUpdateRequest updateRrequest = new RecommendedUpdateRequest(newUrl);
67+
68+
//when
69+
recommendedService.update(recommendedPostId, updateRrequest);
70+
Optional<RecommendedPost> actual = recommendedRepository.findById(recommendedPostId);
71+
72+
//then
73+
assertThat(actual.get().getUrl()).isEqualTo(newUrl);
74+
}
75+
76+
@Test
77+
@DisplayName("추천 포스트 삭제 테스트")
78+
void delete() {
79+
//given
80+
final RecommendedRequest request = new RecommendedRequest("https//:example.com");
81+
Long recommendedPostId = recommendedService.create(keyword.getId(), request);
82+
83+
//when
84+
recommendedService.delete(recommendedPostId);
85+
86+
//then
87+
assertSoftly(softAssertions -> {
88+
assertThat(recommendedRepository.findAll()).hasSize(0);
89+
assertThat(keywordRepository.findById(keyword.getId()).get().getRecommendedPosts())
90+
.isEmpty();
91+
});
92+
}
93+
}

0 commit comments

Comments
 (0)