From 2e2c1ca8b9f54f46670cffa23472592c11f5629a Mon Sep 17 00:00:00 2001 From: luckhee Date: Mon, 22 Sep 2025 12:41:48 +0900 Subject: [PATCH 1/8] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=8B=A4?= =?UTF-8?q?=EA=B1=B4=20=EC=A1=B0=ED=9A=8C=20&&=20=EB=8B=A8=EA=B1=B4?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20TC=20=EC=9E=91=EC=84=B1=20&&=20Init=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/back/global/init/PostInitData.java | 46 +++++++++++++++++ .../InformationPostControllerTest.java | 50 +++++++------------ 2 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 back/src/main/java/com/back/global/init/PostInitData.java diff --git a/back/src/main/java/com/back/global/init/PostInitData.java b/back/src/main/java/com/back/global/init/PostInitData.java new file mode 100644 index 00000000..b65c7a6a --- /dev/null +++ b/back/src/main/java/com/back/global/init/PostInitData.java @@ -0,0 +1,46 @@ +package com.back.global.init; + +import com.back.domain.post.entity.Post; +import com.back.domain.post.repository.PostRepository; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Component; + +@Profile("test") +@Component +@RequiredArgsConstructor +@Slf4j +public class PostInitData implements ApplicationRunner { + private final PostRepository postRepository; + + + @Override + public void run(ApplicationArguments args) throws Exception { + log.info("postinit데이터 생성"); + initPostData(); + log.info("postinit데이터 생성 완료"); + } + + @Transactional + protected void initPostData() { + if (postRepository.count() > 0) return; + + // 여러 종류의 게시글 생성 + createPost("정보글 제목", "정보글 내용", Post.PostType.INFORMATIONPOST); + createPost("연습글 제목", "연습글 내용", Post.PostType.PRACTICEPOST); + createPost("질문글 제목", "질문글 내용", Post.PostType.QUESTIONPOST); + } + + private void createPost(String title, String content, Post.PostType type) { + Post post = new Post(); + post.setTitle(title); + post.setContent(content); + post.setAuthorName("테스트유저"); + post.setPostType(type); + postRepository.save(post); + } +} diff --git a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java index ee751913..661a453a 100644 --- a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java +++ b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java @@ -88,7 +88,7 @@ void t1() throws Exception { .andDo(print()); // 실제 생성된 게시글 조회 (실제 DB에서) - Post createdPost = postService.findById(1L); + Post createdPost = postService.findById(4L); resultActions .andExpect(handler().handlerType(InformationPostController.class)) @@ -145,35 +145,21 @@ void t3() throws Exception { .andExpect(jsonPath("$.data").exists()); } -// @Test -// @DisplayName("게시글 단건조회") -// void t4() throws Exception { -// Post mockPost = new Post(); -// -// // 리플렉션으로 ID 설정 -// Field idField = BaseEntity.class.getDeclaredField("id"); -// idField.setAccessible(true); -// idField.set(mockPost, 1L); -// -// mockPost.setTitle("테스트 제목"); -// mockPost.setContent("테스트 내용"); -// mockPost.setAuthorName("테스트유저"); -// mockPost.setPostType(Post.PostType.INFORMATIONPOST); -// -// when(postService.findById(1L)).thenReturn(mockPost); -// -// ResultActions resultActions = mvc -// .perform( -// get("/post/infor/{post_id}", 1L) -// ) -// .andDo(print()); -// -// -// resultActions -// .andExpect(handler().handlerType(InformationPostController.class)) -// .andExpect(handler().methodName("getSinglePost")) -// .andExpect(status().isOk()) -// .andExpect(jsonPath("$.message").value("게시글 단건 조회 성공")) -// .andExpect(jsonPath("$.data").exists()); -// } + @Test + @DisplayName("게시글 단건조회") + void t4() throws Exception { + ResultActions resultActions = mvc + .perform( + get("/post/infor/{post_id}", 1L) + ) + .andDo(print()); + + + resultActions + .andExpect(handler().handlerType(InformationPostController.class)) + .andExpect(handler().methodName("getSinglePost")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").value("게시글 단건 조회 성공")) + .andExpect(jsonPath("$.data").exists()); + } } From e54138881473237b92632367ce14fca5d13e334b Mon Sep 17 00:00:00 2001 From: luckhee Date: Mon, 22 Sep 2025 14:21:23 +0900 Subject: [PATCH 2/8] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EC=9C=A0=ED=9A=A8=EC=84=B1=EA=B4=80=EB=A0=A8=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/InformationPostController.java | 3 +- .../domain/post/dto/PostCreateRequest.java | 4 +- .../com/back/domain/post/entity/Post.java | 4 ++ .../com/back/domain/post/rq/ApiResponse.java | 6 +-- .../InformationPostControllerTest.java | 51 +++++++++++++++++-- 5 files changed, 60 insertions(+), 8 deletions(-) diff --git a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java index 9616272e..4fe19306 100644 --- a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java +++ b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java @@ -10,6 +10,7 @@ import com.back.domain.post.service.PostService; import com.back.global.auth.CurrentUser; import io.swagger.v3.oas.annotations.Operation; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -26,7 +27,7 @@ public class InformationPostController { @Operation(summary = "게시글 생성") @PostMapping public ResponseEntity> createPost( - @RequestBody PostCreateRequest postCreateRequest, + @Valid @RequestBody PostCreateRequest postCreateRequest, @CurrentUser Member member ) { String authorName = member.getName(); diff --git a/back/src/main/java/com/back/domain/post/dto/PostCreateRequest.java b/back/src/main/java/com/back/domain/post/dto/PostCreateRequest.java index 84684fd6..8c249e85 100644 --- a/back/src/main/java/com/back/domain/post/dto/PostCreateRequest.java +++ b/back/src/main/java/com/back/domain/post/dto/PostCreateRequest.java @@ -1,12 +1,14 @@ package com.back.domain.post.dto; +import jakarta.validation.constraints.NotBlank; import lombok.Data; @Data public class PostCreateRequest { private Long memberId; private String postType; + @NotBlank(message = "제목은 null 혹은 공백일 수 없습니다.") private String title; + @NotBlank(message = "제목은 null 혹은 공백일 수 없습니다.") private String content; - } diff --git a/back/src/main/java/com/back/domain/post/entity/Post.java b/back/src/main/java/com/back/domain/post/entity/Post.java index fa12a4c8..8cfa699a 100644 --- a/back/src/main/java/com/back/domain/post/entity/Post.java +++ b/back/src/main/java/com/back/domain/post/entity/Post.java @@ -4,6 +4,7 @@ import jakarta.persistence.Entity; import jakarta.persistence.EnumType; import jakarta.persistence.Enumerated; +import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -13,8 +14,11 @@ @Getter @Setter public class Post extends BaseEntity { + @NotNull(message = "제목은 null일 수 없습니다.") private String title; + @NotNull private String content; + @NotNull private String authorName; @Enumerated(EnumType.STRING) diff --git a/back/src/main/java/com/back/domain/post/rq/ApiResponse.java b/back/src/main/java/com/back/domain/post/rq/ApiResponse.java index d999348b..4b056d40 100644 --- a/back/src/main/java/com/back/domain/post/rq/ApiResponse.java +++ b/back/src/main/java/com/back/domain/post/rq/ApiResponse.java @@ -4,12 +4,12 @@ @Getter public class ApiResponse { - private String message; + private String msg; private T data; - public ApiResponse(String message, T data) { - this.message= message; + public ApiResponse(String msg, T data) { + this.msg = msg; this.data = data; } } diff --git a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java index 661a453a..6b06aa19 100644 --- a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java +++ b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java @@ -94,12 +94,39 @@ void t1() throws Exception { .andExpect(handler().handlerType(InformationPostController.class)) .andExpect(handler().methodName("createPost")) .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").value("게시글이 성공적으로 생성되었습니다. ")) + .andExpect(jsonPath("$.msg").value("게시글이 성공적으로 생성되었습니다. ")) .andExpect(jsonPath("$.data").exists()) .andExpect(jsonPath("$.data.postId").value(createdPost.getId())) .andExpect(jsonPath("$.data.title").value(createdPost.getTitle())); } + @Test + @DisplayName("게시글 생성 실패 (제목 null)") + void t6() throws Exception { + ResultActions resultActions = mvc + .perform( + post("/post/infor") + .contentType(MediaType.APPLICATION_JSON) + .content(""" + { + "memberId": 1, + "postType": "INFORMATIONPOST", + "title": "", + "content": "테스트 내용" + } + """.stripIndent()) + ) + .andDo(print()); + + + resultActions + .andExpect(handler().handlerType(InformationPostController.class)) + .andExpect(handler().methodName("createPost")) + + .andExpect(status().isBadRequest()) + .andExpect(jsonPath("$.msg").value("title-NotBlank-제목은 null 혹은 공백일 수 없습니다.")); + } + @Test @DisplayName("일치하지 않는 postType") void t2() throws Exception { @@ -141,7 +168,7 @@ void t3() throws Exception { .andExpect(handler().methodName("getAllPost")) .andExpect(status().isOk()) .andExpect(jsonPath("$.data").isArray()) - .andExpect(jsonPath("$.message").value("게시글 다건 조회 성공")) + .andExpect(jsonPath("$.msg").value("게시글 다건 조회 성공")) .andExpect(jsonPath("$.data").exists()); } @@ -159,7 +186,25 @@ void t4() throws Exception { .andExpect(handler().handlerType(InformationPostController.class)) .andExpect(handler().methodName("getSinglePost")) .andExpect(status().isOk()) - .andExpect(jsonPath("$.message").value("게시글 단건 조회 성공")) + .andExpect(jsonPath("$.msg").value("게시글 단건 조회 성공")) + .andExpect(jsonPath("$.data.id").value(1L)) + .andExpect(jsonPath("$.data.title").value("정보글 제목")) .andExpect(jsonPath("$.data").exists()); } + + @Test + @DisplayName("게시글 단건조회 실패 (유효하지 않은 Id") + void t5() throws Exception { + ResultActions resultActions = mvc + .perform( + get("/post/infor/{post_id}", 999L) + ) + .andDo(print()); + + resultActions + .andExpect(handler().handlerType(InformationPostController.class)) + .andExpect(handler().methodName("getSinglePost")) + .andExpect(jsonPath("$.resultCode").value("400")) + .andExpect(jsonPath("$.msg").value("해당 Id의 게시글이 없습니다.")); + } } From abcdb8122497665ed842eadd54886697285acfef Mon Sep 17 00:00:00 2001 From: luckhee Date: Mon, 22 Sep 2025 21:26:02 +0900 Subject: [PATCH 3/8] =?UTF-8?q?=ED=83=80=EC=9E=85=20=EB=B3=84=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20=EC=9C=84=EC=B9=98=20=EB=B6=84=EB=A5=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/InformationPostController.java | 2 +- .../post/repository/PostRepository.java | 1 + .../repository/PracticePostRepository.java | 10 +++ .../repository/QuestionPostRepository.java | 10 +++ .../back/domain/post/service/PostService.java | 71 +++++++++++++------ .../com/back/global/init/PostInitData.java | 49 ++++++++++++- .../security/CustomAuthenticationFilter.java | 1 + .../InformationPostControllerTest.java | 8 +-- 8 files changed, 122 insertions(+), 30 deletions(-) create mode 100644 back/src/main/java/com/back/domain/post/repository/PracticePostRepository.java create mode 100644 back/src/main/java/com/back/domain/post/repository/QuestionPostRepository.java diff --git a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java index 4fe19306..ba6941aa 100644 --- a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java +++ b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java @@ -50,7 +50,7 @@ public ResponseEntity>> getAllPost() { @Operation(summary = "게시글 단건 조회") @GetMapping("/{post_id}") public ResponseEntity> getSinglePost(@PathVariable long post_id) { - Post post = postService.findById(post_id); + Post post = postService.findById(post_id, "INFORMATIONPOST"); PostSingleResponse postSingleResponse = new PostSingleResponse(post); diff --git a/back/src/main/java/com/back/domain/post/repository/PostRepository.java b/back/src/main/java/com/back/domain/post/repository/PostRepository.java index 628d0fa8..8d33692c 100644 --- a/back/src/main/java/com/back/domain/post/repository/PostRepository.java +++ b/back/src/main/java/com/back/domain/post/repository/PostRepository.java @@ -6,4 +6,5 @@ @Repository public interface PostRepository extends JpaRepository { + } diff --git a/back/src/main/java/com/back/domain/post/repository/PracticePostRepository.java b/back/src/main/java/com/back/domain/post/repository/PracticePostRepository.java new file mode 100644 index 00000000..015e0a2f --- /dev/null +++ b/back/src/main/java/com/back/domain/post/repository/PracticePostRepository.java @@ -0,0 +1,10 @@ +package com.back.domain.post.repository; + +import com.back.domain.post.entity.PracticePost; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PracticePostRepository extends JpaRepository { + +} diff --git a/back/src/main/java/com/back/domain/post/repository/QuestionPostRepository.java b/back/src/main/java/com/back/domain/post/repository/QuestionPostRepository.java new file mode 100644 index 00000000..8d45b7c0 --- /dev/null +++ b/back/src/main/java/com/back/domain/post/repository/QuestionPostRepository.java @@ -0,0 +1,10 @@ +package com.back.domain.post.repository; + +import com.back.domain.post.entity.QuestionPost; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface QuestionPostRepository extends JpaRepository { + +} diff --git a/back/src/main/java/com/back/domain/post/service/PostService.java b/back/src/main/java/com/back/domain/post/service/PostService.java index 0f69cf8c..46d8b210 100644 --- a/back/src/main/java/com/back/domain/post/service/PostService.java +++ b/back/src/main/java/com/back/domain/post/service/PostService.java @@ -3,7 +3,11 @@ import com.back.domain.post.dto.PostAllResponse; import com.back.domain.post.dto.PostCreateRequest; import com.back.domain.post.entity.Post; +import com.back.domain.post.entity.PracticePost; +import com.back.domain.post.entity.QuestionPost; import com.back.domain.post.repository.PostRepository; +import com.back.domain.post.repository.PracticePostRepository; +import com.back.domain.post.repository.QuestionPostRepository; import com.back.global.exception.ServiceException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -15,6 +19,8 @@ public class PostService { private final PostRepository postRepository; + private final PracticePostRepository practicePostRepository; + private final QuestionPostRepository questionPostRepository; public List getAllPosts() { List posts = postRepository.findAll(); @@ -24,36 +30,57 @@ public List getAllPosts() { public Post createPost(PostCreateRequest postCreateRequest, String authorName) { - Post post = new Post(); + String postTypeStr = postCreateRequest.getPostType(); + validPostType(postTypeStr); + + Post.PostType postType = Post.PostType.valueOf(postTypeStr); + + Post post = createPostByType(postType); post.setTitle(postCreateRequest.getTitle()); post.setContent(postCreateRequest.getContent()); post.setAuthorName(authorName); - String postTypeStr = postCreateRequest.getPostType(); - Post.PostType postType; - - switch(postTypeStr) { - case "INFORMATIONPOST": - postType = Post.PostType.INFORMATIONPOST; - break; - case "PRACTICEPOST": - postType = Post.PostType.PRACTICEPOST; - break; - case "QUESTIONPOST": - postType = Post.PostType.QUESTIONPOST; - break; - default: - throw new ServiceException("400-2", "유효하지 않은 PostType입니다."); - } - post.setPostType(postType); - postRepository.save(post); + return saveByType(post); + } + + private Post createPostByType(Post.PostType postType) { + return switch (postType) { + case INFORMATIONPOST -> new Post(); + case PRACTICEPOST -> new PracticePost(); + case QUESTIONPOST -> new QuestionPost(); + }; + } - return post; + private Post saveByType(Post post) { + return switch (post.getPostType()) { + case INFORMATIONPOST -> postRepository.save(post); + case PRACTICEPOST -> practicePostRepository.save((PracticePost) post); + case QUESTIONPOST -> questionPostRepository.save((QuestionPost) post); + }; } - public Post findById(Long id) { - return postRepository.findById(id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + private void validPostType(String postTypeStr) { + boolean eq = false; + + String[] validType = new String[3]; + validType[0] = "INFORMATIONPOST"; + validType[1] = "PRACTICEPOST"; + validType[2] = "QUESTIONPOST"; + + for(String x : validType) if(x.equals(postTypeStr)) eq = true; + + if(!eq) throw new ServiceException("400-2", "유효하지 않은 PostType입니다."); + } + + + public Post findById(Long id, String category) { + Post.PostType postType = Post.PostType.valueOf(category); + return switch (postType) { + case INFORMATIONPOST -> postRepository.findById(id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + case PRACTICEPOST -> practicePostRepository.findById(id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + case QUESTIONPOST -> questionPostRepository.findById(id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + }; } public List getAllPostResponse() { diff --git a/back/src/main/java/com/back/global/init/PostInitData.java b/back/src/main/java/com/back/global/init/PostInitData.java index b65c7a6a..1f3c7932 100644 --- a/back/src/main/java/com/back/global/init/PostInitData.java +++ b/back/src/main/java/com/back/global/init/PostInitData.java @@ -1,7 +1,12 @@ package com.back.global.init; import com.back.domain.post.entity.Post; +import com.back.domain.post.entity.PracticePost; +import com.back.domain.post.entity.QuestionPost; import com.back.domain.post.repository.PostRepository; +import com.back.domain.post.repository.PracticePostRepository; +import com.back.domain.post.repository.QuestionPostRepository; +import com.back.global.exception.ServiceException; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -17,11 +22,17 @@ public class PostInitData implements ApplicationRunner { private final PostRepository postRepository; + private final PracticePostRepository practicePostRepository; + private final QuestionPostRepository questionPostRepository; @Override public void run(ApplicationArguments args) throws Exception { log.info("postinit데이터 생성"); initPostData(); + long count = practicePostRepository.count(); + log.info("PracticePost개수는 " + count); + log.info("postRepo개수는 " + postRepository.count()); + log.info("questionPostRepo 개수는 " + questionPostRepository.count()); log.info("postinit데이터 생성 완료"); } @@ -36,11 +47,45 @@ protected void initPostData() { } private void createPost(String title, String content, Post.PostType type) { - Post post = new Post(); + validPostType(String.valueOf(type)); + + Post post = createPostByType(type); post.setTitle(title); post.setContent(content); post.setAuthorName("테스트유저"); post.setPostType(type); - postRepository.save(post); + + saveByType(post); + } + + /// /////// + + private Post createPostByType(Post.PostType postType) { + return switch (postType) { + case INFORMATIONPOST -> new Post(); + case PRACTICEPOST -> new PracticePost(); + case QUESTIONPOST -> new QuestionPost(); + }; + } + + private Post saveByType(Post post) { + return switch (post.getPostType()) { + case INFORMATIONPOST -> postRepository.save(post); + case PRACTICEPOST -> practicePostRepository.save((PracticePost) post); + case QUESTIONPOST -> questionPostRepository.save((QuestionPost) post); + }; + } + + private void validPostType(String postTypeStr) { + boolean eq = false; + + String[] validType = new String[3]; + validType[0] = "INFORMATIONPOST"; + validType[1] = "PRACTICEPOST"; + validType[2] = "QUESTIONPOST"; + + for(String x : validType) if(x.equals(postTypeStr)) eq = true; + + if(!eq) throw new ServiceException("400-2", "유효하지 않은 PostType입니다."); } } diff --git a/back/src/main/java/com/back/global/security/CustomAuthenticationFilter.java b/back/src/main/java/com/back/global/security/CustomAuthenticationFilter.java index 5f66e8a7..27b732be 100644 --- a/back/src/main/java/com/back/global/security/CustomAuthenticationFilter.java +++ b/back/src/main/java/com/back/global/security/CustomAuthenticationFilter.java @@ -37,6 +37,7 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse try { work(request, response, filterChain); } catch (Exception e) { + log.error("CustomAuthenticationFilter에서 예외 발생: ",e); RsData rsData = new RsData<>("401-1", "인증 오류가 발생했습니다."); response.setContentType("application/json;charset=UTF-8"); response.setStatus(rsData.statusCode()); diff --git a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java index 6b06aa19..0c5a8a48 100644 --- a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java +++ b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java @@ -38,9 +38,6 @@ public class InformationPostControllerTest { @Autowired private PostService postService; -// @MockBean -// private PostService postMockService; - @Autowired private MemberService memberService; @@ -79,7 +76,7 @@ void t1() throws Exception { .content(""" { "memberId": 1, - "postType": "INFORMATIONPOST", + "postType": "QUESTIONPOST", "title": "테스트 제목", "content": "테스트 내용" } @@ -87,8 +84,9 @@ void t1() throws Exception { ) .andDo(print()); + String type = "QUESTIONPOST"; // 실제 생성된 게시글 조회 (실제 DB에서) - Post createdPost = postService.findById(4L); + Post createdPost = postService.findById(4L, type); resultActions .andExpect(handler().handlerType(InformationPostController.class)) From 0ff447376aa115be2510922e7618b9f15dd38a63 Mon Sep 17 00:00:00 2001 From: luckhee Date: Tue, 23 Sep 2025 10:44:06 +0900 Subject: [PATCH 4/8] =?UTF-8?q?Post=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EA=B4=80=EB=A0=A8=20=20=EB=A6=AC=ED=8C=A9=ED=86=A0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/InformationPostController.java | 13 +++++- .../com/back/domain/post/entity/Post.java | 5 +++ .../back/domain/post/entity/PracticePost.java | 11 ----- .../back/domain/post/entity/QuestionPost.java | 8 ---- .../repository/PracticePostRepository.java | 10 ----- .../repository/QuestionPostRepository.java | 10 ----- .../back/domain/post/service/PostService.java | 41 +++++-------------- .../com/back/global/init/PostInitData.java | 34 +++------------ .../InformationPostControllerTest.java | 3 +- 9 files changed, 35 insertions(+), 100 deletions(-) delete mode 100644 back/src/main/java/com/back/domain/post/entity/PracticePost.java delete mode 100644 back/src/main/java/com/back/domain/post/entity/QuestionPost.java delete mode 100644 back/src/main/java/com/back/domain/post/repository/PracticePostRepository.java delete mode 100644 back/src/main/java/com/back/domain/post/repository/QuestionPostRepository.java diff --git a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java index ba6941aa..00042151 100644 --- a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java +++ b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java @@ -50,11 +50,22 @@ public ResponseEntity>> getAllPost() { @Operation(summary = "게시글 단건 조회") @GetMapping("/{post_id}") public ResponseEntity> getSinglePost(@PathVariable long post_id) { - Post post = postService.findById(post_id, "INFORMATIONPOST"); + Post post = postService.findById(post_id); PostSingleResponse postSingleResponse = new PostSingleResponse(post); ApiResponse response = new ApiResponse<>("게시글 단건 조회 성공", postSingleResponse); return ResponseEntity.ok(response); } + +// @Operation(summary = "게시글 삭제") +// @DeleteMapping("/{post_id}") +// public ResponseEntity> removePost(@PathVariable long post_id) { +// Post post = postService.findById(post_id, "INFORMATIONPOST"); +// +// postService.removePost(post_id); +// +// ApiResponse response = new ApiResponse<>("게시글 단건 조회 성공", postSingleResponse); +// return ResponseEntity.ok(response); +// } } diff --git a/back/src/main/java/com/back/domain/post/entity/Post.java b/back/src/main/java/com/back/domain/post/entity/Post.java index 8cfa699a..b2275dd6 100644 --- a/back/src/main/java/com/back/domain/post/entity/Post.java +++ b/back/src/main/java/com/back/domain/post/entity/Post.java @@ -34,4 +34,9 @@ public enum PostType { private int liked; + private Boolean isMento; + private String carrer; + + private Boolean isResolve; + } diff --git a/back/src/main/java/com/back/domain/post/entity/PracticePost.java b/back/src/main/java/com/back/domain/post/entity/PracticePost.java deleted file mode 100644 index 6c9940a6..00000000 --- a/back/src/main/java/com/back/domain/post/entity/PracticePost.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.back.domain.post.entity; - -import jakarta.persistence.Entity; -import lombok.NoArgsConstructor; - -@Entity -@NoArgsConstructor -public class PracticePost extends Post{ - private Boolean isMento; - private String carrer; -} diff --git a/back/src/main/java/com/back/domain/post/entity/QuestionPost.java b/back/src/main/java/com/back/domain/post/entity/QuestionPost.java deleted file mode 100644 index 5a9c49f8..00000000 --- a/back/src/main/java/com/back/domain/post/entity/QuestionPost.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.back.domain.post.entity; - -import jakarta.persistence.Entity; - -@Entity -public class QuestionPost extends Post{ - private Boolean isResolve; -} diff --git a/back/src/main/java/com/back/domain/post/repository/PracticePostRepository.java b/back/src/main/java/com/back/domain/post/repository/PracticePostRepository.java deleted file mode 100644 index 015e0a2f..00000000 --- a/back/src/main/java/com/back/domain/post/repository/PracticePostRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.back.domain.post.repository; - -import com.back.domain.post.entity.PracticePost; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface PracticePostRepository extends JpaRepository { - -} diff --git a/back/src/main/java/com/back/domain/post/repository/QuestionPostRepository.java b/back/src/main/java/com/back/domain/post/repository/QuestionPostRepository.java deleted file mode 100644 index 8d45b7c0..00000000 --- a/back/src/main/java/com/back/domain/post/repository/QuestionPostRepository.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.back.domain.post.repository; - -import com.back.domain.post.entity.QuestionPost; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.stereotype.Repository; - -@Repository -public interface QuestionPostRepository extends JpaRepository { - -} diff --git a/back/src/main/java/com/back/domain/post/service/PostService.java b/back/src/main/java/com/back/domain/post/service/PostService.java index 46d8b210..9937c96b 100644 --- a/back/src/main/java/com/back/domain/post/service/PostService.java +++ b/back/src/main/java/com/back/domain/post/service/PostService.java @@ -3,11 +3,7 @@ import com.back.domain.post.dto.PostAllResponse; import com.back.domain.post.dto.PostCreateRequest; import com.back.domain.post.entity.Post; -import com.back.domain.post.entity.PracticePost; -import com.back.domain.post.entity.QuestionPost; import com.back.domain.post.repository.PostRepository; -import com.back.domain.post.repository.PracticePostRepository; -import com.back.domain.post.repository.QuestionPostRepository; import com.back.global.exception.ServiceException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -19,8 +15,6 @@ public class PostService { private final PostRepository postRepository; - private final PracticePostRepository practicePostRepository; - private final QuestionPostRepository questionPostRepository; public List getAllPosts() { List posts = postRepository.findAll(); @@ -35,29 +29,15 @@ public Post createPost(PostCreateRequest postCreateRequest, String authorName) { Post.PostType postType = Post.PostType.valueOf(postTypeStr); - Post post = createPostByType(postType); + Post post = new Post(); post.setTitle(postCreateRequest.getTitle()); post.setContent(postCreateRequest.getContent()); post.setAuthorName(authorName); post.setPostType(postType); - return saveByType(post); - } - - private Post createPostByType(Post.PostType postType) { - return switch (postType) { - case INFORMATIONPOST -> new Post(); - case PRACTICEPOST -> new PracticePost(); - case QUESTIONPOST -> new QuestionPost(); - }; - } + postRepository.save(post); - private Post saveByType(Post post) { - return switch (post.getPostType()) { - case INFORMATIONPOST -> postRepository.save(post); - case PRACTICEPOST -> practicePostRepository.save((PracticePost) post); - case QUESTIONPOST -> questionPostRepository.save((QuestionPost) post); - }; + return post; } private void validPostType(String postTypeStr) { @@ -74,13 +54,9 @@ private void validPostType(String postTypeStr) { } - public Post findById(Long id, String category) { - Post.PostType postType = Post.PostType.valueOf(category); - return switch (postType) { - case INFORMATIONPOST -> postRepository.findById(id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); - case PRACTICEPOST -> practicePostRepository.findById(id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); - case QUESTIONPOST -> questionPostRepository.findById(id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); - }; + public Post findById(Long id) { + Post post = postRepository.findById(id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + return post; } public List getAllPostResponse() { @@ -88,4 +64,9 @@ public List getAllPostResponse() { .map(PostAllResponse::new) .toList(); } + + public void removePost(Long post_id) { + Post post = postRepository.findById(post_id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + + } } diff --git a/back/src/main/java/com/back/global/init/PostInitData.java b/back/src/main/java/com/back/global/init/PostInitData.java index 1f3c7932..994e5ad4 100644 --- a/back/src/main/java/com/back/global/init/PostInitData.java +++ b/back/src/main/java/com/back/global/init/PostInitData.java @@ -1,11 +1,7 @@ package com.back.global.init; import com.back.domain.post.entity.Post; -import com.back.domain.post.entity.PracticePost; -import com.back.domain.post.entity.QuestionPost; import com.back.domain.post.repository.PostRepository; -import com.back.domain.post.repository.PracticePostRepository; -import com.back.domain.post.repository.QuestionPostRepository; import com.back.global.exception.ServiceException; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; @@ -22,17 +18,16 @@ public class PostInitData implements ApplicationRunner { private final PostRepository postRepository; - private final PracticePostRepository practicePostRepository; - private final QuestionPostRepository questionPostRepository; + @Override public void run(ApplicationArguments args) throws Exception { log.info("postinit데이터 생성"); initPostData(); - long count = practicePostRepository.count(); - log.info("PracticePost개수는 " + count); + + log.info("postRepo개수는 " + postRepository.count()); - log.info("questionPostRepo 개수는 " + questionPostRepository.count()); + log.info("postinit데이터 생성 완료"); } @@ -49,32 +44,15 @@ protected void initPostData() { private void createPost(String title, String content, Post.PostType type) { validPostType(String.valueOf(type)); - Post post = createPostByType(type); + Post post = new Post(); post.setTitle(title); post.setContent(content); post.setAuthorName("테스트유저"); post.setPostType(type); - saveByType(post); + postRepository.save(post); } - /// /////// - - private Post createPostByType(Post.PostType postType) { - return switch (postType) { - case INFORMATIONPOST -> new Post(); - case PRACTICEPOST -> new PracticePost(); - case QUESTIONPOST -> new QuestionPost(); - }; - } - - private Post saveByType(Post post) { - return switch (post.getPostType()) { - case INFORMATIONPOST -> postRepository.save(post); - case PRACTICEPOST -> practicePostRepository.save((PracticePost) post); - case QUESTIONPOST -> questionPostRepository.save((QuestionPost) post); - }; - } private void validPostType(String postTypeStr) { boolean eq = false; diff --git a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java index 0c5a8a48..5e476769 100644 --- a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java +++ b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java @@ -84,9 +84,8 @@ void t1() throws Exception { ) .andDo(print()); - String type = "QUESTIONPOST"; // 실제 생성된 게시글 조회 (실제 DB에서) - Post createdPost = postService.findById(4L, type); + Post createdPost = postService.findById(4L); resultActions .andExpect(handler().handlerType(InformationPostController.class)) From 5f948b3b63ca45ef942b2913b01c9821c096cf9d Mon Sep 17 00:00:00 2001 From: luckhee Date: Tue, 23 Sep 2025 11:44:49 +0900 Subject: [PATCH 5/8] =?UTF-8?q?=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EC=99=84?= =?UTF-8?q?=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/InformationPostController.java | 43 +++++++------- .../com/back/domain/post/entity/Post.java | 8 ++- .../back/domain/post/service/PostService.java | 14 ++++- .../com/back/global/init/PostInitData.java | 20 +++++-- .../InformationPostControllerTest.java | 57 +++++++++++++++++-- 5 files changed, 102 insertions(+), 40 deletions(-) diff --git a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java index 00042151..3d572fc2 100644 --- a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java +++ b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java @@ -6,13 +6,13 @@ import com.back.domain.post.dto.PostCreateResponse; import com.back.domain.post.dto.PostSingleResponse; import com.back.domain.post.entity.Post; -import com.back.domain.post.rq.ApiResponse; import com.back.domain.post.service.PostService; import com.back.global.auth.CurrentUser; +import com.back.global.rq.Rq; +import com.back.global.rsData.RsData; import io.swagger.v3.oas.annotations.Operation; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -22,50 +22,47 @@ @RequiredArgsConstructor public class InformationPostController { private final PostService postService; + private final Rq rq; @Operation(summary = "게시글 생성") @PostMapping - public ResponseEntity> createPost( + public RsData createPost( @Valid @RequestBody PostCreateRequest postCreateRequest, @CurrentUser Member member ) { - String authorName = member.getName(); - Post post = postService.createPost(postCreateRequest, authorName); + + Post post = postService.createPost(postCreateRequest, member); PostCreateResponse postCreateResponse = PostCreateResponse.from(post); - ApiResponse response = new ApiResponse<>("게시글이 성공적으로 생성되었습니다. " , postCreateResponse); - return ResponseEntity.ok(response); + + return new RsData<>("200", "게시글이 성공적으로 생성되었습니다.", postCreateResponse); } @Operation(summary = "게시글 다건 조회") @GetMapping - public ResponseEntity>> getAllPost() { + public RsData> getAllPost() { List postAllResponse = postService.getAllPostResponse(); - ApiResponse> response = new ApiResponse<>("게시글 다건 조회 성공", postAllResponse); - return ResponseEntity.ok(response); + return new RsData<>("200", "게시글 다건 조회 성공", postAllResponse); } @Operation(summary = "게시글 단건 조회") @GetMapping("/{post_id}") - public ResponseEntity> getSinglePost(@PathVariable long post_id) { + public RsData getSinglePost(@PathVariable long post_id) { Post post = postService.findById(post_id); PostSingleResponse postSingleResponse = new PostSingleResponse(post); - ApiResponse response = new ApiResponse<>("게시글 단건 조회 성공", postSingleResponse); - return ResponseEntity.ok(response); + return new RsData<>("200", "게시글 단건 조회 성공", postSingleResponse); } -// @Operation(summary = "게시글 삭제") -// @DeleteMapping("/{post_id}") -// public ResponseEntity> removePost(@PathVariable long post_id) { -// Post post = postService.findById(post_id, "INFORMATIONPOST"); -// -// postService.removePost(post_id); -// -// ApiResponse response = new ApiResponse<>("게시글 단건 조회 성공", postSingleResponse); -// return ResponseEntity.ok(response); -// } + @Operation(summary = "게시글 삭제") + @DeleteMapping("/{post_id}") + public RsData removePost(@PathVariable long post_id, @CurrentUser Member member) { + + postService.removePost(post_id, member); + + return new RsData<>("200", "게시글 삭제 성공", null); + } } diff --git a/back/src/main/java/com/back/domain/post/entity/Post.java b/back/src/main/java/com/back/domain/post/entity/Post.java index b2275dd6..365649e0 100644 --- a/back/src/main/java/com/back/domain/post/entity/Post.java +++ b/back/src/main/java/com/back/domain/post/entity/Post.java @@ -1,9 +1,8 @@ package com.back.domain.post.entity; +import com.back.domain.member.member.entity.Member; import com.back.global.jpa.BaseEntity; -import jakarta.persistence.Entity; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; +import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; import lombok.Getter; import lombok.NoArgsConstructor; @@ -21,6 +20,9 @@ public class Post extends BaseEntity { @NotNull private String authorName; + @ManyToOne(fetch = FetchType.LAZY) + private Member member; + @Enumerated(EnumType.STRING) private PostType postType; diff --git a/back/src/main/java/com/back/domain/post/service/PostService.java b/back/src/main/java/com/back/domain/post/service/PostService.java index 9937c96b..c5b5607c 100644 --- a/back/src/main/java/com/back/domain/post/service/PostService.java +++ b/back/src/main/java/com/back/domain/post/service/PostService.java @@ -1,5 +1,6 @@ package com.back.domain.post.service; +import com.back.domain.member.member.entity.Member; import com.back.domain.post.dto.PostAllResponse; import com.back.domain.post.dto.PostCreateRequest; import com.back.domain.post.entity.Post; @@ -23,16 +24,20 @@ public List getAllPosts() { } - public Post createPost(PostCreateRequest postCreateRequest, String authorName) { + public Post createPost(PostCreateRequest postCreateRequest,Member member) { String postTypeStr = postCreateRequest.getPostType(); + validPostType(postTypeStr); + + Post.PostType postType = Post.PostType.valueOf(postTypeStr); Post post = new Post(); post.setTitle(postCreateRequest.getTitle()); post.setContent(postCreateRequest.getContent()); - post.setAuthorName(authorName); + post.setAuthorName(member.getName()); + post.setMember(member); post.setPostType(postType); postRepository.save(post); @@ -65,8 +70,11 @@ public List getAllPostResponse() { .toList(); } - public void removePost(Long post_id) { + public void removePost(Long post_id, Member member) { Post post = postRepository.findById(post_id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + Long authorId = post.getMember().getId(); + if(authorId != member.getId()) throw new ServiceException("400", "삭제 권한이 없습니다."); + postRepository.delete(post); } } diff --git a/back/src/main/java/com/back/global/init/PostInitData.java b/back/src/main/java/com/back/global/init/PostInitData.java index 994e5ad4..53af36a9 100644 --- a/back/src/main/java/com/back/global/init/PostInitData.java +++ b/back/src/main/java/com/back/global/init/PostInitData.java @@ -1,5 +1,7 @@ package com.back.global.init; +import com.back.domain.member.member.entity.Member; +import com.back.domain.member.member.service.MemberService; import com.back.domain.post.entity.Post; import com.back.domain.post.repository.PostRepository; import com.back.global.exception.ServiceException; @@ -17,7 +19,7 @@ @Slf4j public class PostInitData implements ApplicationRunner { private final PostRepository postRepository; - + private final MemberService memberService; @Override @@ -31,17 +33,22 @@ public void run(ApplicationArguments args) throws Exception { log.info("postinit데이터 생성 완료"); } + + @Transactional protected void initPostData() { if (postRepository.count() > 0) return; - + Member member2 = memberService.join("user2", "사용자1", "password123", Member.Role.MENTEE); + Member member3 = memberService.join("user3", "사용자1", "password123", Member.Role.MENTEE); + Member member4 = memberService.join("user4", "사용자1", "password123", Member.Role.MENTEE); + Member member5 = memberService.join("user5", "사용자1", "password123", Member.Role.MENTEE); // 여러 종류의 게시글 생성 - createPost("정보글 제목", "정보글 내용", Post.PostType.INFORMATIONPOST); - createPost("연습글 제목", "연습글 내용", Post.PostType.PRACTICEPOST); - createPost("질문글 제목", "질문글 내용", Post.PostType.QUESTIONPOST); + createPost("정보글 제목", "정보글 내용", member2, Post.PostType.INFORMATIONPOST); + createPost("연습글 제목", "연습글 내용", member3, Post.PostType.PRACTICEPOST); + createPost("질문글 제목", "질문글 내용", member4, Post.PostType.QUESTIONPOST); } - private void createPost(String title, String content, Post.PostType type) { + private void createPost(String title, String content, Member member, Post.PostType type) { validPostType(String.valueOf(type)); Post post = new Post(); @@ -49,6 +56,7 @@ private void createPost(String title, String content, Post.PostType type) { post.setContent(content); post.setAuthorName("테스트유저"); post.setPostType(type); + post.setMember(member); postRepository.save(post); } diff --git a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java index 5e476769..ea8d5732 100644 --- a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java +++ b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java @@ -8,6 +8,7 @@ import jakarta.transaction.Transactional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -23,8 +24,7 @@ import java.util.List; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @@ -91,14 +91,14 @@ void t1() throws Exception { .andExpect(handler().handlerType(InformationPostController.class)) .andExpect(handler().methodName("createPost")) .andExpect(status().isOk()) - .andExpect(jsonPath("$.msg").value("게시글이 성공적으로 생성되었습니다. ")) + .andExpect(jsonPath("$.msg").value("게시글이 성공적으로 생성되었습니다.")) .andExpect(jsonPath("$.data").exists()) .andExpect(jsonPath("$.data.postId").value(createdPost.getId())) .andExpect(jsonPath("$.data.title").value(createdPost.getTitle())); } @Test - @DisplayName("게시글 생성 실패 (제목 null)") + @DisplayName("게시글 생성 실패 - 제목 null") void t6() throws Exception { ResultActions resultActions = mvc .perform( @@ -190,7 +190,7 @@ void t4() throws Exception { } @Test - @DisplayName("게시글 단건조회 실패 (유효하지 않은 Id") + @DisplayName("게시글 단건조회 실패 - 유효하지 않은 Id") void t5() throws Exception { ResultActions resultActions = mvc .perform( @@ -204,4 +204,51 @@ void t5() throws Exception { .andExpect(jsonPath("$.resultCode").value("400")) .andExpect(jsonPath("$.msg").value("해당 Id의 게시글이 없습니다.")); } + + @Test + @Order(7) + @DisplayName("게시글 삭제") + void t7() throws Exception { + mvc.perform( + post("/post/infor") + .contentType(MediaType.APPLICATION_JSON) + .content(""" + { + "memberId": 1, + "postType": "INFORMATIONPOST", + "title": "삭제용 제목", + "content": "삭제용 내용" + } + """) + ); + + + ResultActions resultActions = mvc + .perform( + delete("/post/infor/{post_id}", 5L) + ) + .andDo(print()); + + resultActions + .andExpect(handler().handlerType(InformationPostController.class)) + .andExpect(handler().methodName("removePost")) + .andExpect(jsonPath("$.resultCode").value("200")) + .andExpect(jsonPath("$.msg").value("게시글 삭제 성공")); + } + + @Test + @DisplayName("게시글 삭제 실패 - 권한 없는 사용자") + void t8() throws Exception { + ResultActions resultActions = mvc + .perform( + delete("/post/infor/{post_id}", 3L) + ) + .andDo(print()); + + resultActions + .andExpect(handler().handlerType(InformationPostController.class)) + .andExpect(handler().methodName("removePost")) + .andExpect(jsonPath("$.resultCode").value("400")) + .andExpect(jsonPath("$.msg").value("삭제 권한이 없습니다.")); + } } From bf0d3fb4454f11fe27abee6922872c3e300578ee Mon Sep 17 00:00:00 2001 From: luckhee Date: Tue, 23 Sep 2025 14:11:01 +0900 Subject: [PATCH 6/8] =?UTF-8?q?=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EC=A2=8B?= =?UTF-8?q?=EC=95=84=EC=9A=94=20=EC=8B=AB=EC=96=B4=EC=9A=94=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/InformationPostController.java | 49 +++++++++-- .../domain/post/dto/PostLikedResponse.java | 9 ++ .../domain/post/dto/PostModifyRequest.java | 9 ++ .../back/domain/post/service/PostService.java | 39 ++++++++- .../InformationPostControllerTest.java | 86 ++++++++++++++++++- 5 files changed, 178 insertions(+), 14 deletions(-) create mode 100644 back/src/main/java/com/back/domain/post/dto/PostLikedResponse.java create mode 100644 back/src/main/java/com/back/domain/post/dto/PostModifyRequest.java diff --git a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java index 3d572fc2..2bd26c7b 100644 --- a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java +++ b/back/src/main/java/com/back/domain/post/controller/InformationPostController.java @@ -1,10 +1,7 @@ package com.back.domain.post.controller; import com.back.domain.member.member.entity.Member; -import com.back.domain.post.dto.PostAllResponse; -import com.back.domain.post.dto.PostCreateRequest; -import com.back.domain.post.dto.PostCreateResponse; -import com.back.domain.post.dto.PostSingleResponse; +import com.back.domain.post.dto.*; import com.back.domain.post.entity.Post; import com.back.domain.post.service.PostService; import com.back.global.auth.CurrentUser; @@ -28,10 +25,9 @@ public class InformationPostController { @Operation(summary = "게시글 생성") @PostMapping public RsData createPost( - @Valid @RequestBody PostCreateRequest postCreateRequest, - @CurrentUser Member member + @Valid @RequestBody PostCreateRequest postCreateRequest ) { - + Member member = rq.getActor(); Post post = postService.createPost(postCreateRequest, member); PostCreateResponse postCreateResponse = PostCreateResponse.from(post); @@ -59,10 +55,47 @@ public RsData getSinglePost(@PathVariable long post_id) { @Operation(summary = "게시글 삭제") @DeleteMapping("/{post_id}") - public RsData removePost(@PathVariable long post_id, @CurrentUser Member member) { + public RsData removePost(@PathVariable long post_id) { + Member member = rq.getActor(); postService.removePost(post_id, member); return new RsData<>("200", "게시글 삭제 성공", null); } + + @Operation(summary = "게시글 수정") + @PutMapping("/{post_id}") + public RsData updatePost(@PathVariable long post_id + ,@CurrentUser Member member + ,@Valid @RequestBody PostCreateRequest postCreateRequest) { + + postService.updatePost(post_id, member, postCreateRequest); + + return new RsData<>("200", "게시글 수정 성공", null); + } + + @Operation(summary = "게시글 좋아요 + ") + @PostMapping("/{post_id}/liked") + public RsData likePost(@PathVariable long post_id) { + postService.likePost(post_id); + + return new RsData<>("200", "게시글 좋아요 성공", null); + } + + @Operation(summary = "게시글 좋아요 (Show)") + @GetMapping("/{post_id}/liked") + public RsData getlike(@PathVariable long post_id) { + int likeCount = postService.showLikeCount(post_id); + PostLikedResponse postLikedResponse = new PostLikedResponse(likeCount); + + return new RsData<>("200", "게시글 좋아요 조회 성공", postLikedResponse); + } + + @Operation(summary = "게시글 싫어요") + @PostMapping("/{post_id}/disliked") + public RsData disLikePost(@PathVariable long post_id) { + postService.disLikePost(post_id); + + return new RsData<>("200", "게시글 싫어요 성공", null); + } } diff --git a/back/src/main/java/com/back/domain/post/dto/PostLikedResponse.java b/back/src/main/java/com/back/domain/post/dto/PostLikedResponse.java new file mode 100644 index 00000000..cc835c0c --- /dev/null +++ b/back/src/main/java/com/back/domain/post/dto/PostLikedResponse.java @@ -0,0 +1,9 @@ +package com.back.domain.post.dto; + +public class PostLikedResponse { + int liked; + + public PostLikedResponse(int liked) { + this.liked= liked; + } +} diff --git a/back/src/main/java/com/back/domain/post/dto/PostModifyRequest.java b/back/src/main/java/com/back/domain/post/dto/PostModifyRequest.java new file mode 100644 index 00000000..9ed233c6 --- /dev/null +++ b/back/src/main/java/com/back/domain/post/dto/PostModifyRequest.java @@ -0,0 +1,9 @@ +package com.back.domain.post.dto; + +import lombok.Data; + +@Data +public class PostModifyRequest { + String title; + String content; +} diff --git a/back/src/main/java/com/back/domain/post/service/PostService.java b/back/src/main/java/com/back/domain/post/service/PostService.java index c5b5607c..8d6e166c 100644 --- a/back/src/main/java/com/back/domain/post/service/PostService.java +++ b/back/src/main/java/com/back/domain/post/service/PostService.java @@ -6,6 +6,7 @@ import com.back.domain.post.entity.Post; import com.back.domain.post.repository.PostRepository; import com.back.global.exception.ServiceException; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -59,8 +60,8 @@ private void validPostType(String postTypeStr) { } - public Post findById(Long id) { - Post post = postRepository.findById(id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + public Post findById(Long postId) { + Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); return post; } @@ -70,11 +71,41 @@ public List getAllPostResponse() { .toList(); } - public void removePost(Long post_id, Member member) { - Post post = postRepository.findById(post_id).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + public void removePost(Long postId, Member member) { + Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); Long authorId = post.getMember().getId(); if(authorId != member.getId()) throw new ServiceException("400", "삭제 권한이 없습니다."); postRepository.delete(post); } + + public void updatePost(long postId, Member member, @Valid PostCreateRequest postCreateRequest) { + Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + Long authorId = post.getMember().getId(); + if(authorId != member.getId()) throw new ServiceException("400", "수정 권한이 없습니다."); + + post.setTitle(postCreateRequest.getTitle()); + post.setContent(postCreateRequest.getContent()); + + postRepository.save(post); + } + + public void likePost(long postId) { + Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + + post.setLiked(post.getLiked()+1); + } + + public void disLikePost(long postId) { + Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + + post.setLiked(post.getLiked()-1); + } + + public int showLikeCount(long postId) { + Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + + int count = post.getLiked(); + return count; + } } diff --git a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java index ea8d5732..cc5a784b 100644 --- a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java +++ b/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java @@ -8,7 +8,6 @@ import jakarta.transaction.Transactional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -206,7 +205,6 @@ void t5() throws Exception { } @Test - @Order(7) @DisplayName("게시글 삭제") void t7() throws Exception { mvc.perform( @@ -251,4 +249,88 @@ void t8() throws Exception { .andExpect(jsonPath("$.resultCode").value("400")) .andExpect(jsonPath("$.msg").value("삭제 권한이 없습니다.")); } + + @Test + @DisplayName("게시글 수정") + void t9() throws Exception { + mvc.perform( + post("/post/infor") + .contentType(MediaType.APPLICATION_JSON) + .content(""" + { + "memberId": 1, + "postType": "INFORMATIONPOST", + "title": "삭제용 제목", + "content": "삭제용 내용" + } + """) + ); + + + ResultActions resultActions = mvc + .perform( + put("/post/infor/{post_id}", 6L) + .contentType(MediaType.APPLICATION_JSON) + .content(""" + { + "title": "수정용 제목", + "content": "수정용 내용" + } + """) + ) + .andDo(print()); + + resultActions + .andExpect(handler().handlerType(InformationPostController.class)) + .andExpect(handler().methodName("updatePost")) + .andExpect(jsonPath("$.resultCode").value("200")) + .andExpect(jsonPath("$.msg").value("게시글 수정 성공")); + } + + @Test + @DisplayName("게시글 수정 실패 - 권한 없는 사용자") + void t10() throws Exception { + ResultActions resultActions = mvc + .perform( + put("/post/infor/{post_id}", 2L) + .contentType(MediaType.APPLICATION_JSON) + .content(""" + { + "title": "수정용 제목", + "content": "수정용 내용" + } + """) + ) + .andDo(print()); + + resultActions + .andExpect(handler().handlerType(InformationPostController.class)) + .andExpect(handler().methodName("updatePost")) + .andExpect(jsonPath("$.resultCode").value("400")) + .andExpect(jsonPath("$.msg").value("수정 권한이 없습니다.")); + } + + @Test + @DisplayName("게시글 수정 실패 - title blank") + void t11() throws Exception { + ResultActions resultActions = mvc + .perform( + put("/post/infor/{post_id}", 6L) + .contentType(MediaType.APPLICATION_JSON) + .content(""" + { + "title": "", + "content": "수정용 내용" + } + """) + ) + .andDo(print()); + + resultActions + .andExpect(handler().handlerType(InformationPostController.class)) + .andExpect(handler().methodName("updatePost")) + .andExpect(jsonPath("$.resultCode").value("400-1")) + .andExpect(jsonPath("$.msg").value("title-NotBlank-제목은 null 혹은 공백일 수 없습니다.")); + } + } From 2f9eed94bfeb575556afd3e4a01152d76a76d26f Mon Sep 17 00:00:00 2001 From: luckhee Date: Tue, 23 Sep 2025 15:51:03 +0900 Subject: [PATCH 7/8] =?UTF-8?q?=20=EA=B2=8C=EC=8B=9C=EA=B8=80=20=EB=8C=93?= =?UTF-8?q?=EA=B8=80=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/PostCommentController.java | 33 ++++++ .../comment/dto/CommentCreateRequest.java | 10 ++ .../post/comment/entity/PostComment.java | 26 +++++ .../repository/PostCommentRepository.java | 9 ++ .../comment/service/PostCommentService.java | 35 ++++++ .../controller/InformationPostController.java | 8 +- .../post/{ => post}/dto/PostAllResponse.java | 4 +- .../{ => post}/dto/PostCreateRequest.java | 2 +- .../{ => post}/dto/PostCreateResponse.java | 4 +- .../{ => post}/dto/PostLikedResponse.java | 2 +- .../{ => post}/dto/PostModifyRequest.java | 2 +- .../{ => post}/dto/PostSingleResponse.java | 4 +- .../domain/post/{ => post}/entity/Post.java | 20 +++- .../{ => post}/repository/PostRepository.java | 4 +- .../post/{ => post}/rq/ApiResponse.java | 2 +- .../post/{ => post}/service/PostService.java | 12 +-- .../com/back/global/init/PostInitData.java | 4 +- ...{CommentTest.java => PostCommentTest.java} | 4 +- ...eTest.java => PostCommentServiceTest.java} | 4 +- .../comment/PostCommentControllerTest.java | 100 ++++++++++++++++++ .../InformationPostControllerTest.java | 7 +- 21 files changed, 264 insertions(+), 32 deletions(-) create mode 100644 back/src/main/java/com/back/domain/post/comment/controller/PostCommentController.java create mode 100644 back/src/main/java/com/back/domain/post/comment/dto/CommentCreateRequest.java create mode 100644 back/src/main/java/com/back/domain/post/comment/entity/PostComment.java create mode 100644 back/src/main/java/com/back/domain/post/comment/repository/PostCommentRepository.java create mode 100644 back/src/main/java/com/back/domain/post/comment/service/PostCommentService.java rename back/src/main/java/com/back/domain/post/{ => post}/controller/InformationPostController.java (94%) rename back/src/main/java/com/back/domain/post/{ => post}/dto/PostAllResponse.java (86%) rename back/src/main/java/com/back/domain/post/{ => post}/dto/PostCreateRequest.java (90%) rename back/src/main/java/com/back/domain/post/{ => post}/dto/PostCreateResponse.java (80%) rename back/src/main/java/com/back/domain/post/{ => post}/dto/PostLikedResponse.java (76%) rename back/src/main/java/com/back/domain/post/{ => post}/dto/PostModifyRequest.java (72%) rename back/src/main/java/com/back/domain/post/{ => post}/dto/PostSingleResponse.java (86%) rename back/src/main/java/com/back/domain/post/{ => post}/entity/Post.java (62%) rename back/src/main/java/com/back/domain/post/{ => post}/repository/PostRepository.java (68%) rename back/src/main/java/com/back/domain/post/{ => post}/rq/ApiResponse.java (84%) rename back/src/main/java/com/back/domain/post/{ => post}/service/PostService.java (91%) rename back/src/test/java/com/back/domain/news/comment/entity/{CommentTest.java => PostCommentTest.java} (99%) rename back/src/test/java/com/back/domain/news/comment/service/{CommentServiceTest.java => PostCommentServiceTest.java} (99%) create mode 100644 back/src/test/java/com/back/domain/post/comment/PostCommentControllerTest.java rename back/src/test/java/com/back/domain/post/{ => post}/controller/InformationPostControllerTest.java (98%) diff --git a/back/src/main/java/com/back/domain/post/comment/controller/PostCommentController.java b/back/src/main/java/com/back/domain/post/comment/controller/PostCommentController.java new file mode 100644 index 00000000..5fcc5af3 --- /dev/null +++ b/back/src/main/java/com/back/domain/post/comment/controller/PostCommentController.java @@ -0,0 +1,33 @@ +package com.back.domain.post.comment.controller; + +import com.back.domain.member.member.entity.Member; +import com.back.domain.post.comment.dto.CommentCreateRequest; +import com.back.domain.post.comment.service.PostCommentService; +import com.back.global.rq.Rq; +import com.back.global.rsData.RsData; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/post/comment") +@RequiredArgsConstructor +public class PostCommentController { + @Autowired + private Rq rq; + @Autowired + private PostCommentService postCommentService; + + @Operation(summary = "댓글 생성") + @PostMapping("/{post_id}") + public RsData createComment(@PathVariable Long post_id, + @Valid @RequestBody CommentCreateRequest commentCreateRequest + ) { + Member member = rq.getActor(); + postCommentService.createComment(member, post_id, commentCreateRequest); + + return new RsData<>("200", "댓글 작성 완료" , null); + } +} diff --git a/back/src/main/java/com/back/domain/post/comment/dto/CommentCreateRequest.java b/back/src/main/java/com/back/domain/post/comment/dto/CommentCreateRequest.java new file mode 100644 index 00000000..95286991 --- /dev/null +++ b/back/src/main/java/com/back/domain/post/comment/dto/CommentCreateRequest.java @@ -0,0 +1,10 @@ +package com.back.domain.post.comment.dto; + +import lombok.Data; + +@Data +public class CommentCreateRequest { + private Long postId; + private String role; + private String comment; +} diff --git a/back/src/main/java/com/back/domain/post/comment/entity/PostComment.java b/back/src/main/java/com/back/domain/post/comment/entity/PostComment.java new file mode 100644 index 00000000..208e1210 --- /dev/null +++ b/back/src/main/java/com/back/domain/post/comment/entity/PostComment.java @@ -0,0 +1,26 @@ +package com.back.domain.post.comment.entity; + +import com.back.domain.member.member.entity.Member; +import com.back.domain.post.post.entity.Post; +import com.back.global.jpa.BaseEntity; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.ManyToOne; +import lombok.Getter; +import lombok.Setter; + +@Entity +@Getter +@Setter +public class PostComment extends BaseEntity { + @ManyToOne(fetch = FetchType.LAZY) + private Post post; + + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + private Member member; + + private String role; + +} diff --git a/back/src/main/java/com/back/domain/post/comment/repository/PostCommentRepository.java b/back/src/main/java/com/back/domain/post/comment/repository/PostCommentRepository.java new file mode 100644 index 00000000..1c2ab975 --- /dev/null +++ b/back/src/main/java/com/back/domain/post/comment/repository/PostCommentRepository.java @@ -0,0 +1,9 @@ +package com.back.domain.post.comment.repository; + +import com.back.domain.post.comment.entity.PostComment; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PostCommentRepository extends JpaRepository { +} diff --git a/back/src/main/java/com/back/domain/post/comment/service/PostCommentService.java b/back/src/main/java/com/back/domain/post/comment/service/PostCommentService.java new file mode 100644 index 00000000..0f75febb --- /dev/null +++ b/back/src/main/java/com/back/domain/post/comment/service/PostCommentService.java @@ -0,0 +1,35 @@ +package com.back.domain.post.comment.service; + +import com.back.domain.member.member.entity.Member; +import com.back.domain.post.comment.dto.CommentCreateRequest; +import com.back.domain.post.comment.entity.PostComment; +import com.back.domain.post.comment.repository.PostCommentRepository; +import com.back.domain.post.post.entity.Post; +import com.back.domain.post.post.repository.PostRepository; +import com.back.global.exception.ServiceException; +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class PostCommentService { + private final PostRepository postRepository; + private final PostCommentRepository postCommentRepository; + + @Transactional + public void createComment(Member member, Long postId, CommentCreateRequest commentCreateRequest) { + Post post = postRepository.findById(postId).orElseThrow(() -> new ServiceException("400", "해당 Id의 게시글이 없습니다.")); + + PostComment postComment = new PostComment(); + + postComment.setContent(commentCreateRequest.getComment()); + postComment.setMember(member); + postComment.setRole(String.valueOf(member.getRole())); + + post.addComment(postComment); + + postCommentRepository.save(postComment); + + } +} diff --git a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java b/back/src/main/java/com/back/domain/post/post/controller/InformationPostController.java similarity index 94% rename from back/src/main/java/com/back/domain/post/controller/InformationPostController.java rename to back/src/main/java/com/back/domain/post/post/controller/InformationPostController.java index 2bd26c7b..679b7ad9 100644 --- a/back/src/main/java/com/back/domain/post/controller/InformationPostController.java +++ b/back/src/main/java/com/back/domain/post/post/controller/InformationPostController.java @@ -1,9 +1,9 @@ -package com.back.domain.post.controller; +package com.back.domain.post.post.controller; import com.back.domain.member.member.entity.Member; -import com.back.domain.post.dto.*; -import com.back.domain.post.entity.Post; -import com.back.domain.post.service.PostService; +import com.back.domain.post.post.dto.*; +import com.back.domain.post.post.entity.Post; +import com.back.domain.post.post.service.PostService; import com.back.global.auth.CurrentUser; import com.back.global.rq.Rq; import com.back.global.rsData.RsData; diff --git a/back/src/main/java/com/back/domain/post/dto/PostAllResponse.java b/back/src/main/java/com/back/domain/post/post/dto/PostAllResponse.java similarity index 86% rename from back/src/main/java/com/back/domain/post/dto/PostAllResponse.java rename to back/src/main/java/com/back/domain/post/post/dto/PostAllResponse.java index 7760b45e..ca25dcce 100644 --- a/back/src/main/java/com/back/domain/post/dto/PostAllResponse.java +++ b/back/src/main/java/com/back/domain/post/post/dto/PostAllResponse.java @@ -1,6 +1,6 @@ -package com.back.domain.post.dto; +package com.back.domain.post.post.dto; -import com.back.domain.post.entity.Post; +import com.back.domain.post.post.entity.Post; import lombok.Data; import java.time.LocalDateTime; diff --git a/back/src/main/java/com/back/domain/post/dto/PostCreateRequest.java b/back/src/main/java/com/back/domain/post/post/dto/PostCreateRequest.java similarity index 90% rename from back/src/main/java/com/back/domain/post/dto/PostCreateRequest.java rename to back/src/main/java/com/back/domain/post/post/dto/PostCreateRequest.java index 8c249e85..1ff1838c 100644 --- a/back/src/main/java/com/back/domain/post/dto/PostCreateRequest.java +++ b/back/src/main/java/com/back/domain/post/post/dto/PostCreateRequest.java @@ -1,4 +1,4 @@ -package com.back.domain.post.dto; +package com.back.domain.post.post.dto; import jakarta.validation.constraints.NotBlank; import lombok.Data; diff --git a/back/src/main/java/com/back/domain/post/dto/PostCreateResponse.java b/back/src/main/java/com/back/domain/post/post/dto/PostCreateResponse.java similarity index 80% rename from back/src/main/java/com/back/domain/post/dto/PostCreateResponse.java rename to back/src/main/java/com/back/domain/post/post/dto/PostCreateResponse.java index c3b5505b..da16a1d2 100644 --- a/back/src/main/java/com/back/domain/post/dto/PostCreateResponse.java +++ b/back/src/main/java/com/back/domain/post/post/dto/PostCreateResponse.java @@ -1,6 +1,6 @@ -package com.back.domain.post.dto; +package com.back.domain.post.post.dto; -import com.back.domain.post.entity.Post; +import com.back.domain.post.post.entity.Post; import lombok.Data; @Data diff --git a/back/src/main/java/com/back/domain/post/dto/PostLikedResponse.java b/back/src/main/java/com/back/domain/post/post/dto/PostLikedResponse.java similarity index 76% rename from back/src/main/java/com/back/domain/post/dto/PostLikedResponse.java rename to back/src/main/java/com/back/domain/post/post/dto/PostLikedResponse.java index cc835c0c..95ac2847 100644 --- a/back/src/main/java/com/back/domain/post/dto/PostLikedResponse.java +++ b/back/src/main/java/com/back/domain/post/post/dto/PostLikedResponse.java @@ -1,4 +1,4 @@ -package com.back.domain.post.dto; +package com.back.domain.post.post.dto; public class PostLikedResponse { int liked; diff --git a/back/src/main/java/com/back/domain/post/dto/PostModifyRequest.java b/back/src/main/java/com/back/domain/post/post/dto/PostModifyRequest.java similarity index 72% rename from back/src/main/java/com/back/domain/post/dto/PostModifyRequest.java rename to back/src/main/java/com/back/domain/post/post/dto/PostModifyRequest.java index 9ed233c6..0ff0b8c7 100644 --- a/back/src/main/java/com/back/domain/post/dto/PostModifyRequest.java +++ b/back/src/main/java/com/back/domain/post/post/dto/PostModifyRequest.java @@ -1,4 +1,4 @@ -package com.back.domain.post.dto; +package com.back.domain.post.post.dto; import lombok.Data; diff --git a/back/src/main/java/com/back/domain/post/dto/PostSingleResponse.java b/back/src/main/java/com/back/domain/post/post/dto/PostSingleResponse.java similarity index 86% rename from back/src/main/java/com/back/domain/post/dto/PostSingleResponse.java rename to back/src/main/java/com/back/domain/post/post/dto/PostSingleResponse.java index 4e40ce19..6c079709 100644 --- a/back/src/main/java/com/back/domain/post/dto/PostSingleResponse.java +++ b/back/src/main/java/com/back/domain/post/post/dto/PostSingleResponse.java @@ -1,6 +1,6 @@ -package com.back.domain.post.dto; +package com.back.domain.post.post.dto; -import com.back.domain.post.entity.Post; +import com.back.domain.post.post.entity.Post; import lombok.Data; import java.time.LocalDateTime; diff --git a/back/src/main/java/com/back/domain/post/entity/Post.java b/back/src/main/java/com/back/domain/post/post/entity/Post.java similarity index 62% rename from back/src/main/java/com/back/domain/post/entity/Post.java rename to back/src/main/java/com/back/domain/post/post/entity/Post.java index 365649e0..8370f49f 100644 --- a/back/src/main/java/com/back/domain/post/entity/Post.java +++ b/back/src/main/java/com/back/domain/post/post/entity/Post.java @@ -1,6 +1,7 @@ -package com.back.domain.post.entity; +package com.back.domain.post.post.entity; import com.back.domain.member.member.entity.Member; +import com.back.domain.post.comment.entity.PostComment; import com.back.global.jpa.BaseEntity; import jakarta.persistence.*; import jakarta.validation.constraints.NotNull; @@ -8,6 +9,9 @@ import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.ArrayList; +import java.util.List; + @Entity @NoArgsConstructor @Getter @@ -32,6 +36,9 @@ public enum PostType { QUESTIONPOST } + @OneToMany(mappedBy = "post", cascade = CascadeType.ALL, orphanRemoval = true) + private List comments = new ArrayList<>(); + private int viewCount; private int liked; @@ -41,4 +48,15 @@ public enum PostType { private Boolean isResolve; + + + public void addComment(PostComment comment) { + comments.add(comment); + comment.setPost(this); + } + + public void removeComment(PostComment comment) { + comments.remove(comment); + comment.setPost(null); + } } diff --git a/back/src/main/java/com/back/domain/post/repository/PostRepository.java b/back/src/main/java/com/back/domain/post/post/repository/PostRepository.java similarity index 68% rename from back/src/main/java/com/back/domain/post/repository/PostRepository.java rename to back/src/main/java/com/back/domain/post/post/repository/PostRepository.java index 8d33692c..d48774c3 100644 --- a/back/src/main/java/com/back/domain/post/repository/PostRepository.java +++ b/back/src/main/java/com/back/domain/post/post/repository/PostRepository.java @@ -1,6 +1,6 @@ -package com.back.domain.post.repository; +package com.back.domain.post.post.repository; -import com.back.domain.post.entity.Post; +import com.back.domain.post.post.entity.Post; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; diff --git a/back/src/main/java/com/back/domain/post/rq/ApiResponse.java b/back/src/main/java/com/back/domain/post/post/rq/ApiResponse.java similarity index 84% rename from back/src/main/java/com/back/domain/post/rq/ApiResponse.java rename to back/src/main/java/com/back/domain/post/post/rq/ApiResponse.java index 4b056d40..7af57293 100644 --- a/back/src/main/java/com/back/domain/post/rq/ApiResponse.java +++ b/back/src/main/java/com/back/domain/post/post/rq/ApiResponse.java @@ -1,4 +1,4 @@ -package com.back.domain.post.rq; +package com.back.domain.post.post.rq; import lombok.Getter; diff --git a/back/src/main/java/com/back/domain/post/service/PostService.java b/back/src/main/java/com/back/domain/post/post/service/PostService.java similarity index 91% rename from back/src/main/java/com/back/domain/post/service/PostService.java rename to back/src/main/java/com/back/domain/post/post/service/PostService.java index 8d6e166c..fe37fe37 100644 --- a/back/src/main/java/com/back/domain/post/service/PostService.java +++ b/back/src/main/java/com/back/domain/post/post/service/PostService.java @@ -1,10 +1,10 @@ -package com.back.domain.post.service; +package com.back.domain.post.post.service; import com.back.domain.member.member.entity.Member; -import com.back.domain.post.dto.PostAllResponse; -import com.back.domain.post.dto.PostCreateRequest; -import com.back.domain.post.entity.Post; -import com.back.domain.post.repository.PostRepository; +import com.back.domain.post.post.dto.PostAllResponse; +import com.back.domain.post.post.dto.PostCreateRequest; +import com.back.domain.post.post.entity.Post; +import com.back.domain.post.post.repository.PostRepository; import com.back.global.exception.ServiceException; import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; @@ -25,7 +25,7 @@ public List getAllPosts() { } - public Post createPost(PostCreateRequest postCreateRequest,Member member) { + public Post createPost(PostCreateRequest postCreateRequest, Member member) { String postTypeStr = postCreateRequest.getPostType(); validPostType(postTypeStr); diff --git a/back/src/main/java/com/back/global/init/PostInitData.java b/back/src/main/java/com/back/global/init/PostInitData.java index 53af36a9..936e861c 100644 --- a/back/src/main/java/com/back/global/init/PostInitData.java +++ b/back/src/main/java/com/back/global/init/PostInitData.java @@ -2,8 +2,8 @@ import com.back.domain.member.member.entity.Member; import com.back.domain.member.member.service.MemberService; -import com.back.domain.post.entity.Post; -import com.back.domain.post.repository.PostRepository; +import com.back.domain.post.post.entity.Post; +import com.back.domain.post.post.repository.PostRepository; import com.back.global.exception.ServiceException; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; diff --git a/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java b/back/src/test/java/com/back/domain/news/comment/entity/PostCommentTest.java similarity index 99% rename from back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java rename to back/src/test/java/com/back/domain/news/comment/entity/PostCommentTest.java index 24706b3a..85b0d703 100644 --- a/back/src/test/java/com/back/domain/news/comment/entity/CommentTest.java +++ b/back/src/test/java/com/back/domain/news/comment/entity/PostCommentTest.java @@ -10,7 +10,7 @@ import static org.assertj.core.api.Assertions.assertThat; -class CommentTest { +class PostCommentTest { @Test @DisplayName("사용자, 뉴스, 내용으로 댓글 객체 생성") void commentCreationTest() { @@ -104,4 +104,4 @@ void commentUpdateTestWithInvalidContent() { assertThat(e).isInstanceOf(IllegalArgumentException.class); } } -} \ No newline at end of file +} diff --git a/back/src/test/java/com/back/domain/news/comment/service/CommentServiceTest.java b/back/src/test/java/com/back/domain/news/comment/service/PostCommentServiceTest.java similarity index 99% rename from back/src/test/java/com/back/domain/news/comment/service/CommentServiceTest.java rename to back/src/test/java/com/back/domain/news/comment/service/PostCommentServiceTest.java index 6e1abca5..e43b3512 100644 --- a/back/src/test/java/com/back/domain/news/comment/service/CommentServiceTest.java +++ b/back/src/test/java/com/back/domain/news/comment/service/PostCommentServiceTest.java @@ -24,7 +24,7 @@ import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) -class CommentServiceTest { +class PostCommentServiceTest { @Mock private CommentRepository commentRepository; @@ -245,4 +245,4 @@ void deleteComment_WrongNews_ThrowsException() { verify(commentRepository, times(1)).findById(commentId); verify(commentRepository, never()).delete(any(Comment.class)); } -} \ No newline at end of file +} diff --git a/back/src/test/java/com/back/domain/post/comment/PostCommentControllerTest.java b/back/src/test/java/com/back/domain/post/comment/PostCommentControllerTest.java new file mode 100644 index 00000000..9c42160f --- /dev/null +++ b/back/src/test/java/com/back/domain/post/comment/PostCommentControllerTest.java @@ -0,0 +1,100 @@ +package com.back.domain.post.comment; + +import com.back.domain.member.member.entity.Member; +import com.back.domain.member.member.service.MemberService; +import com.back.domain.post.comment.controller.PostCommentController; +import com.back.domain.post.comment.entity.PostComment; +import com.back.domain.post.comment.repository.PostCommentRepository; +import com.back.domain.post.comment.service.PostCommentService; +import com.back.global.security.SecurityUser; +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.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; + +import java.util.List; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@ActiveProfiles("test") +@SpringBootTest +@AutoConfigureMockMvc +@Transactional +public class PostCommentControllerTest { + + @Autowired + private PostCommentService postCommentService; + + @Autowired + private PostCommentRepository postCommentRepository; + + @Autowired + private MemberService memberService; + + @Autowired + private MockMvc mvc; + + @BeforeEach + void setUp() { + Member member = memberService.join("user1", "사용자1", "password123", Member.Role.MENTEE); + + // SecurityContext에 인증 정보 설정 + SecurityUser securityUser = new SecurityUser( + member.getId(), + member.getEmail(), + member.getPassword(), + member.getName(), + List.of(new SimpleGrantedAuthority("ROLE_" + member.getRole().name())) + ); + + Authentication auth = new UsernamePasswordAuthenticationToken( + securityUser, + null, + securityUser.getAuthorities() + ); + + SecurityContextHolder.getContext().setAuthentication(auth); + } + + @Test + @DisplayName("댓글 생성") + void t1() throws Exception { + ResultActions resultActions = mvc + .perform( + post("/post/comment/{post_id}", 1L) + .contentType(MediaType.APPLICATION_JSON) + .content(""" + { + "memberId": 123, + "postId": 1, + "role": "mentor", + "comment": "댓글 내용" + } + """.stripIndent()) + ) + .andDo(print()); + + // 실제 생성된 게시글 조회 (실제 DB에서) + PostComment createdPost = postCommentRepository.findById(1L).get(); + + resultActions + .andExpect(handler().handlerType(PostCommentController.class)) + .andExpect(handler().methodName("createComment")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.msg").value("댓글 작성 완료")); + } + +} diff --git a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java b/back/src/test/java/com/back/domain/post/post/controller/InformationPostControllerTest.java similarity index 98% rename from back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java rename to back/src/test/java/com/back/domain/post/post/controller/InformationPostControllerTest.java index cc5a784b..638954e0 100644 --- a/back/src/test/java/com/back/domain/post/controller/InformationPostControllerTest.java +++ b/back/src/test/java/com/back/domain/post/post/controller/InformationPostControllerTest.java @@ -1,9 +1,10 @@ -package com.back.domain.post.controller; +package com.back.domain.post.post.controller; import com.back.domain.member.member.entity.Member; import com.back.domain.member.member.service.MemberService; -import com.back.domain.post.entity.Post; -import com.back.domain.post.service.PostService; +import com.back.domain.post.post.controller.InformationPostController; +import com.back.domain.post.post.entity.Post; +import com.back.domain.post.post.service.PostService; import com.back.global.security.SecurityUser; import jakarta.transaction.Transactional; import org.junit.jupiter.api.BeforeEach; From 5d1324f87cd265411cb8800ab9a5367141986c6c Mon Sep 17 00:00:00 2001 From: luckhee Date: Tue, 23 Sep 2025 16:16:42 +0900 Subject: [PATCH 8/8] =?UTF-8?q?=EA=B2=8C=EC=8B=9C=EA=B8=80=20CRUD=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- back/src/main/java/com/back/global/init/PostInitData.java | 8 ++++---- .../domain/post/comment/PostCommentControllerTest.java | 2 +- .../post/controller/InformationPostControllerTest.java | 3 +-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/back/src/main/java/com/back/global/init/PostInitData.java b/back/src/main/java/com/back/global/init/PostInitData.java index 936e861c..ac3f67cc 100644 --- a/back/src/main/java/com/back/global/init/PostInitData.java +++ b/back/src/main/java/com/back/global/init/PostInitData.java @@ -38,10 +38,10 @@ public void run(ApplicationArguments args) throws Exception { @Transactional protected void initPostData() { if (postRepository.count() > 0) return; - Member member2 = memberService.join("user2", "사용자1", "password123", Member.Role.MENTEE); - Member member3 = memberService.join("user3", "사용자1", "password123", Member.Role.MENTEE); - Member member4 = memberService.join("user4", "사용자1", "password123", Member.Role.MENTEE); - Member member5 = memberService.join("user5", "사용자1", "password123", Member.Role.MENTEE); + Member member2 = memberService.joinMentee("user2", "사용자1", "password123",""); + Member member3 = memberService.joinMentee("user3", "사용자1", "password123", ""); + Member member4 = memberService.joinMentee("user4", "사용자1", "password123", ""); + Member member5 = memberService.joinMentee("user5", "사용자1", "password123", ""); // 여러 종류의 게시글 생성 createPost("정보글 제목", "정보글 내용", member2, Post.PostType.INFORMATIONPOST); createPost("연습글 제목", "연습글 내용", member3, Post.PostType.PRACTICEPOST); diff --git a/back/src/test/java/com/back/domain/post/comment/PostCommentControllerTest.java b/back/src/test/java/com/back/domain/post/comment/PostCommentControllerTest.java index 9c42160f..309131ac 100644 --- a/back/src/test/java/com/back/domain/post/comment/PostCommentControllerTest.java +++ b/back/src/test/java/com/back/domain/post/comment/PostCommentControllerTest.java @@ -49,7 +49,7 @@ public class PostCommentControllerTest { @BeforeEach void setUp() { - Member member = memberService.join("user1", "사용자1", "password123", Member.Role.MENTEE); + Member member = memberService.joinMentee("user1", "사용자1", "password123", "" ); // SecurityContext에 인증 정보 설정 SecurityUser securityUser = new SecurityUser( diff --git a/back/src/test/java/com/back/domain/post/post/controller/InformationPostControllerTest.java b/back/src/test/java/com/back/domain/post/post/controller/InformationPostControllerTest.java index 638954e0..9a4af6c9 100644 --- a/back/src/test/java/com/back/domain/post/post/controller/InformationPostControllerTest.java +++ b/back/src/test/java/com/back/domain/post/post/controller/InformationPostControllerTest.java @@ -2,7 +2,6 @@ import com.back.domain.member.member.entity.Member; import com.back.domain.member.member.service.MemberService; -import com.back.domain.post.post.controller.InformationPostController; import com.back.domain.post.post.entity.Post; import com.back.domain.post.post.service.PostService; import com.back.global.security.SecurityUser; @@ -46,7 +45,7 @@ public class InformationPostControllerTest { @BeforeEach void setUp() { - Member member = memberService.join("user1", "사용자1", "password123", Member.Role.MENTEE); + Member member = memberService.joinMentee("user1", "사용자1", "password123", ""); // SecurityContext에 인증 정보 설정 SecurityUser securityUser = new SecurityUser(