-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
댓글 조회 기능 구현 #182
댓글 조회 기능 구현 #182
Changes from 5 commits
d90b01f
dd56d26
8ca946e
38dcab7
b2a8b8a
52027c7
8dc2b4b
8bcbf93
d90c171
7ee35bf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package com.votogether.domain.post.dto.response; | ||
|
||
import com.fasterxml.jackson.annotation.JsonFormat; | ||
import com.votogether.domain.member.entity.Member; | ||
import com.votogether.domain.post.entity.comment.Comment; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
import java.time.LocalDateTime; | ||
|
||
@Schema(description = "댓글 응답") | ||
public record CommentResponse( | ||
@Schema(description = "댓글 ID", example = "1") | ||
Long id, | ||
CommentMember member, | ||
@Schema(description = "댓글 내용", example = "재밌어요!") | ||
String content, | ||
@Schema(description = "댓글 작성시각", example = "2023-08-01 10:56") | ||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") | ||
LocalDateTime createdAt, | ||
@Schema(description = "댓글 수정시각", example = "2023-08-01 13:56") | ||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") | ||
LocalDateTime updatedAt | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이것도 record 컨벤션에 대해서 한번 이야기해봐야겠네요! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 라인이 너무 길어보일까봐에 대한 염려도 있었는데 개행을 했더니 더욱 깔끔하게 보이는 거 같네요 ㅎㅎ 수정했습니다! |
||
) { | ||
|
||
public static CommentResponse from(final Comment comment) { | ||
return new CommentResponse( | ||
comment.getId(), | ||
CommentMember.from(comment.getMember()), | ||
comment.getContent(), | ||
comment.getCreatedAt(), | ||
comment.getUpdatedAt() | ||
); | ||
} | ||
|
||
@Schema(description = "댓글 작성자 회원 응답") | ||
record CommentMember( | ||
@Schema(description = "댓글 작성자 회원 ID", example = "1") | ||
Long id, | ||
@Schema(description = "댓글 작성자 회원 닉네임", example = "votogether") | ||
String nickname | ||
) { | ||
|
||
public static CommentMember from(final Member member) { | ||
return new CommentMember(member.getId(), member.getNickname()); | ||
} | ||
|
||
} | ||
Comment on lines
+38
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,14 @@ | ||
package com.votogether.domain.post.repository; | ||
|
||
import com.votogether.domain.post.entity.Post; | ||
import com.votogether.domain.post.entity.comment.Comment; | ||
import java.util.List; | ||
import org.springframework.data.jpa.repository.EntityGraph; | ||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
public interface CommentRepository extends JpaRepository<Comment, Long> { | ||
|
||
@EntityGraph(attributePaths = {"member"}) | ||
List<Comment> findAllByPostOrderByCreatedAtAsc(final Post post); | ||
Comment on lines
+11
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 맞습니다! |
||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
package com.votogether.domain.post.controller; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.hamcrest.Matchers.containsString; | ||
import static org.hamcrest.Matchers.equalTo; | ||
import static org.mockito.ArgumentMatchers.any; | ||
|
@@ -12,11 +13,16 @@ | |
import com.votogether.domain.member.service.MemberService; | ||
import com.votogether.domain.post.dto.request.CommentRegisterRequest; | ||
import com.votogether.domain.post.dto.request.CommentUpdateRequest; | ||
import com.votogether.domain.post.dto.response.CommentResponse; | ||
import com.votogether.domain.post.entity.comment.Comment; | ||
import com.votogether.domain.post.service.PostCommentService; | ||
import com.votogether.fixtures.MemberFixtures; | ||
import com.votogether.global.jwt.TokenPayload; | ||
import com.votogether.global.jwt.TokenProcessor; | ||
import io.restassured.common.mapper.TypeRef; | ||
import io.restassured.module.mockmvc.RestAssuredMockMvc; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Nested; | ||
|
@@ -29,6 +35,7 @@ | |
import org.springframework.http.HttpHeaders; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.test.util.ReflectionTestUtils; | ||
import org.springframework.web.context.WebApplicationContext; | ||
|
||
@WebMvcTest(PostCommentController.class) | ||
|
@@ -122,6 +129,78 @@ void createComment() throws Exception { | |
|
||
} | ||
|
||
@Nested | ||
@DisplayName("게시글 댓글 목록 조회") | ||
class GetComments { | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {"@", "a", "가"}) | ||
@DisplayName("게시글 ID가 Long 타입으로 변환할 수 없는 값이라면 400을 응답한다.") | ||
void invalidPostIDType(String postId) throws Exception { | ||
// given | ||
TokenPayload tokenPayload = new TokenPayload(1L, 1L, 1L); | ||
given(tokenProcessor.resolveToken(anyString())).willReturn("token"); | ||
given(tokenProcessor.parseToken(anyString())).willReturn(tokenPayload); | ||
given(memberService.findById(anyLong())).willReturn(MemberFixtures.MALE_20.get()); | ||
|
||
// when, then | ||
RestAssuredMockMvc.given().log().all() | ||
.headers(HttpHeaders.AUTHORIZATION, "Bearer token") | ||
.when().get("/posts/{postId}/comments", postId) | ||
.then().log().all() | ||
.status(HttpStatus.BAD_REQUEST) | ||
.body("code", equalTo(-9998)) | ||
.body("message", containsString("postId는 Long 타입이 필요합니다.")); | ||
} | ||
|
||
@Test | ||
@DisplayName("정상적인 요청이라면 게시글 댓글 목록을 조회한다.") | ||
void getComments() throws Exception { | ||
// given | ||
TokenPayload tokenPayload = new TokenPayload(1L, 1L, 1L); | ||
given(tokenProcessor.resolveToken(anyString())).willReturn("token"); | ||
given(tokenProcessor.parseToken(anyString())).willReturn(tokenPayload); | ||
given(memberService.findById(anyLong())).willReturn(MemberFixtures.MALE_20.get()); | ||
Comment on lines
+166
to
+169
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 비회원 게시글 조회, 댓글 조회가 가능한 것을 알아버렸습니다 :) 수정완료했습니다 감사합니다 🙇🏻♂️ |
||
|
||
Member memberA = MemberFixtures.MALE_20.get(); | ||
Member memberB = MemberFixtures.FEMALE_20.get(); | ||
ReflectionTestUtils.setField(memberA, "id", 1L); | ||
ReflectionTestUtils.setField(memberB, "id", 2L); | ||
|
||
Comment commentA = Comment.builder() | ||
.member(memberA) | ||
.content("commentA") | ||
.build(); | ||
Comment commentB = Comment.builder() | ||
.member(memberB) | ||
.content("commentA") | ||
.build(); | ||
LocalDateTime now = LocalDateTime.now(); | ||
ReflectionTestUtils.setField(commentA, "createdAt", now); | ||
ReflectionTestUtils.setField(commentB, "createdAt", now); | ||
|
||
CommentResponse commentResponseA = CommentResponse.from(commentA); | ||
CommentResponse commentResponseB = CommentResponse.from(commentB); | ||
given(postCommentService.getComments(anyLong())).willReturn(List.of(commentResponseA, commentResponseB)); | ||
|
||
// when | ||
List<CommentResponse> response = RestAssuredMockMvc.given().log().all() | ||
.headers(HttpHeaders.AUTHORIZATION, "Bearer token") | ||
.when().get("/posts/{postId}/comments", 1L) | ||
.then().log().all() | ||
.status(HttpStatus.OK) | ||
.extract() | ||
.as(new TypeRef<List<CommentResponse>>() { | ||
}); | ||
|
||
// then | ||
assertThat(response).usingRecursiveComparison() | ||
.ignoringFieldsOfTypes(LocalDateTime.class) | ||
.isEqualTo(List.of(commentResponseA, commentResponseB)); | ||
} | ||
|
||
} | ||
|
||
@Nested | ||
@DisplayName("게시글 댓글 수정") | ||
class UpdateComment { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package com.votogether.domain.post.repository; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
|
||
import com.votogether.RepositoryTest; | ||
import com.votogether.domain.member.entity.Member; | ||
import com.votogether.domain.member.repository.MemberRepository; | ||
import com.votogether.domain.post.entity.Post; | ||
import com.votogether.domain.post.entity.PostBody; | ||
import com.votogether.domain.post.entity.comment.Comment; | ||
import com.votogether.fixtures.MemberFixtures; | ||
import java.time.LocalDateTime; | ||
import java.util.List; | ||
import org.junit.jupiter.api.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.springframework.beans.factory.annotation.Autowired; | ||
|
||
@RepositoryTest | ||
class CommentRepositoryTest { | ||
|
||
@Autowired | ||
CommentRepository commentRepository; | ||
|
||
@Autowired | ||
MemberRepository memberRepository; | ||
|
||
@Autowired | ||
PostRepository postRepository; | ||
|
||
@Test | ||
@DisplayName("게시글의 댓글 목록을 조회한다.") | ||
void findAllByPost() { | ||
// given | ||
Member member = memberRepository.save(MemberFixtures.MALE_20.get()); | ||
Post post = postRepository.save( | ||
Post.builder() | ||
.writer(member) | ||
.postBody(PostBody.builder().title("titleA").content("contentA").build()) | ||
.deadline(LocalDateTime.of(2100, 7, 12, 0, 0)) | ||
.build() | ||
); | ||
Comment commentA = commentRepository.save( | ||
Comment.builder() | ||
.member(member) | ||
.post(post) | ||
.content("commentA") | ||
.build() | ||
); | ||
Comment commentB = commentRepository.save( | ||
Comment.builder() | ||
.member(member) | ||
.post(post) | ||
.content("commentB") | ||
.build() | ||
); | ||
|
||
// when | ||
List<Comment> result = commentRepository.findAllByPostOrderByCreatedAtAsc(post); | ||
|
||
// then | ||
assertThat(result).containsExactly(commentA, commentB); | ||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P2
missing final keyword