Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import lombok.Setter;
import lombok.ToString;
import org.sejongisc.backend.board.entity.Board;
import org.sejongisc.backend.user.entity.User;
import org.sejongisc.backend.user.dto.UserInfoResponse;

@ToString
@AllArgsConstructor
Expand All @@ -22,15 +22,15 @@ public class BoardResponse {

private String boardName;

private User createdBy;
private UserInfoResponse createdBy;

private UUID parentBoardId;

public static BoardResponse of(Board board) {
public static BoardResponse from(Board board) {
return BoardResponse.builder()
.boardId(board.getBoardId())
.boardName(board.getBoardName())
.createdBy(board.getCreatedBy())
.createdBy(UserInfoResponse.from(board.getCreatedBy()))
.parentBoardId(board.getParentBoard() != null ? board.getParentBoard().getBoardId() : null)
.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import lombok.Setter;
import lombok.ToString;
import org.sejongisc.backend.board.entity.Comment;
import org.sejongisc.backend.user.entity.User;
import org.sejongisc.backend.user.dto.UserInfoResponse;

@ToString
@AllArgsConstructor
Expand All @@ -20,28 +20,28 @@
@Builder
public class CommentResponse {
private UUID commentId;
private User user;
private UserInfoResponse user;
private UUID postId;
private String content;
private LocalDateTime createdDate;
private LocalDateTime updatedDate;
private List<CommentResponse> replies;

public static CommentResponse of(Comment comment) {
public static CommentResponse from(Comment comment) {
return CommentResponse.builder()
.commentId(comment.getCommentId())
.user(comment.getUser())
.user(UserInfoResponse.from(comment.getUser()))
.postId(comment.getPost().getPostId())
.content(comment.getContent())
.createdDate(comment.getCreatedDate())
.updatedDate(comment.getUpdatedDate())
.build();
}

public static CommentResponse of(Comment comment, List<CommentResponse> replies) {
public static CommentResponse from(Comment comment, List<CommentResponse> replies) {
return CommentResponse.builder()
.commentId(comment.getCommentId())
.user(comment.getUser())
.user(UserInfoResponse.from(comment.getUser()))
.postId(comment.getPost().getPostId())
.content(comment.getContent())
.createdDate(comment.getCreatedDate())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.sejongisc.backend.board.entity.Board;
import org.sejongisc.backend.user.entity.User;
import org.sejongisc.backend.user.dto.UserInfoResponse;
import org.springframework.data.domain.Page;

@ToString
Expand All @@ -22,8 +21,8 @@
public class PostResponse {

private UUID postId;
private Board board;
private User user;
private BoardResponse board;
private UserInfoResponse user;
private String title;
private String content;
private Integer bookmarkCount;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.sejongisc.backend.common.exception.CustomException;
import org.sejongisc.backend.common.exception.ErrorCode;
import org.sejongisc.backend.user.dao.UserRepository;
import org.sejongisc.backend.user.dto.UserInfoResponse;
import org.sejongisc.backend.user.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
Expand Down Expand Up @@ -235,11 +236,11 @@ public PostResponse getPostDetail(UUID postId, int pageNumber, int pageSize) {

// 자식 댓글 목록을 CommentResponse DTO 리스트로 변환
List<CommentResponse> replyResponses = childComments.stream()
.map(CommentResponse::of)
.map(CommentResponse::from)
.toList();

// 부모 댓글 DTO를 생성하며, 자식 DTO 리스트를 주입
return CommentResponse.of(parent, replyResponses);
return CommentResponse.from(parent, replyResponses);
});

// 첨부 파일 조회
Expand All @@ -251,8 +252,8 @@ public PostResponse getPostDetail(UUID postId, int pageNumber, int pageSize) {
// PostResponse DTO를 직접 빌드하여 반환
return PostResponse.builder()
.postId(post.getPostId())
.board(post.getBoard())
.user(post.getUser())
.board(BoardResponse.from(post.getBoard()))
.user(UserInfoResponse.from(post.getUser()))
.title(post.getTitle())
.content(post.getContent())
.bookmarkCount(post.getBookmarkCount())
Expand Down Expand Up @@ -302,15 +303,15 @@ public List<BoardResponse> getParentBoards() {
List<Board> parentBoards = boardRepository.findAllByParentBoardIsNull();

return parentBoards.stream()
.map(BoardResponse::of)
.map(BoardResponse::from)
.toList();
}

private PostResponse mapToPostResponse(Post post) {
return PostResponse.builder()
.postId(post.getPostId())
.user(post.getUser())
.board(post.getBoard())
.user(UserInfoResponse.from(post.getUser()))
.board(BoardResponse.from(post.getBoard()))
.title(post.getTitle())
.content(post.getContent())
.bookmarkCount(post.getBookmarkCount())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package org.sejongisc.backend.user.dto;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.Collection;
import java.util.UUID;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.sejongisc.backend.common.auth.springsecurity.CustomUserDetails;
import org.sejongisc.backend.user.entity.User;

@Getter
@AllArgsConstructor
Expand Down Expand Up @@ -56,4 +57,30 @@ public class UserInfoResponse {
example = "[\"ROLE_USER\"]"
)
private Collection<?> authorities;

public static UserInfoResponse from(CustomUserDetails user) {
if (user == null) {
return null;
}

return new UserInfoResponse(
user.getUserId(),
user.getName(),
user.getEmail(),
user.getPhoneNumber(),
user.getPoint(),
user.getRole().name(),
user.getAuthorities()
);
}

public static UserInfoResponse from(User user) {
if (user == null) {
return null;
}

CustomUserDetails userDetails = new CustomUserDetails(user);

return from(userDetails);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.sejongisc.backend.common.exception.CustomException;
import org.sejongisc.backend.common.exception.ErrorCode;
import org.sejongisc.backend.user.dao.UserRepository;
import org.sejongisc.backend.user.entity.Role; // Role Enum import 필요
import org.sejongisc.backend.user.entity.User;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
Expand Down Expand Up @@ -86,9 +87,28 @@ void setUp() {
boardId = UUID.randomUUID();
postId = UUID.randomUUID();

mockUser = User.builder().userId(userId).build();
mockParentBoard = Board.builder().boardId(UUID.randomUUID()).parentBoard(null).build();
mockBoard = Board.builder().boardId(boardId).parentBoard(mockParentBoard).build();
// DTO 변환(UserInfoResponse.from)시 NPE 방지를 위해 Role, Name, Email 등 필수 필드 세팅
mockUser = User.builder()
.userId(userId)
.email("test@example.com")
.name("Tester")
.role(Role.TEAM_MEMBER) // 또는 Role.USER (프로젝트 Enum 정의에 맞게)
.build();

mockParentBoard = Board.builder()
.boardId(UUID.randomUUID())
.boardName("Parent Board")
.parentBoard(null)
.createdBy(mockUser)
.build();

mockBoard = Board.builder()
.boardId(boardId)
.boardName("Child Board")
.parentBoard(mockParentBoard)
.createdBy(mockUser) // BoardResponse.from 호출 시 필요
.build();

mockPost = Post.builder()
.postId(postId)
.user(mockUser)
Expand Down Expand Up @@ -118,7 +138,7 @@ void savePost_Success() {
when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));
when(fileUploadService.store(any(MultipartFile.class))).thenReturn("saved_filename.txt");
when(fileUploadService.getRootLocation()).thenReturn(Paths.get("test/path"));
when(postRepository.save(any(Post.class))).thenReturn(mockPost); // 저장된 post 반환
when(postRepository.save(any(Post.class))).thenReturn(mockPost);

// when
postService.savePost(request, userId);
Expand Down Expand Up @@ -153,7 +173,7 @@ void updatePost_Success() {
PostRequest request = PostRequest.builder()
.title("Updated Title")
.content("Updated Content")
.files(Collections.emptyList()) // 테스트 편의상 새 파일은 없음
.files(Collections.emptyList())
.build();

PostAttachment oldAttachment = PostAttachment.builder().savedFilename("old_file.txt").build();
Expand All @@ -180,11 +200,11 @@ void updatePost_Fail_InvalidOwner() {
PostRequest request = PostRequest.builder().build();

// Mocking
when(postRepository.findById(postId)).thenReturn(Optional.of(mockPost)); // mockPost의 user는 'userId'
when(postRepository.findById(postId)).thenReturn(Optional.of(mockPost));

// when & then
CustomException exception = assertThrows(CustomException.class, () -> {
postService.updatePost(request, postId, otherUserId); // 다른 'otherUserId'로 수정 시도
postService.updatePost(request, postId, otherUserId);
});

assertThat(exception.getErrorCode()).isEqualTo(ErrorCode.INVALID_POST_OWNER);
Expand Down Expand Up @@ -228,11 +248,16 @@ void getPosts_Success() {
when(postRepository.findAllByBoard(mockBoard, pageable)).thenReturn(postPage);

// when
// 여기서 mapToPostResponse 내부적으로 UserInfoResponse.from(), BoardResponse.from()이 호출됨
// mockUser에 Role 정보가 없으면 NPE 발생 가능 (setUp에서 처리함)
Page<PostResponse> result = postService.getPosts(boardId, page, size);

// then
assertThat(result.getTotalElements()).isEqualTo(1);
assertThat(result.getContent().get(0).getPostId()).isEqualTo(postId);
// DTO 변환 확인
assertThat(result.getContent().get(0).getUser().getName()).isEqualTo(mockUser.getName());
assertThat(result.getContent().get(0).getBoard().getBoardName()).isEqualTo(mockBoard.getBoardName());
}

@Test
Expand All @@ -244,8 +269,21 @@ void getPostDetail_Success_WithReplies() {
Pageable commentPageable = PageRequest.of(page, size, Sort.by(Sort.Direction.ASC, "createdDate"));

// 댓글 Mock 데이터 생성
Comment parentComment = Comment.builder().commentId(UUID.randomUUID()).post(mockPost).content("부모댓글1").parentComment(null).build();
Comment childComment = Comment.builder().commentId(UUID.randomUUID()).post(mockPost).content("대댓글1").parentComment(parentComment).build();
Comment parentComment = Comment.builder()
.commentId(UUID.randomUUID())
.post(mockPost)
.user(mockUser) // 댓글 작성자 필요 (DTO 변환 위해)
.content("부모댓글1")
.parentComment(null)
.build();

Comment childComment = Comment.builder()
.commentId(UUID.randomUUID())
.post(mockPost)
.user(mockUser) // 댓글 작성자 필요
.content("대댓글1")
.parentComment(parentComment)
.build();

Page<Comment> parentCommentPage = new PageImpl<>(List.of(parentComment), commentPageable, 1);

Expand Down Expand Up @@ -293,8 +331,9 @@ void createBoard_Success() {

// Mocking
when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));
when(boardRepository.findById(mockParentBoard.getBoardId())).thenReturn(Optional.of(mockParentBoard));

// ArgumentCaptor: save(board)에 실제 어떤 board 객체가 전달되었는지 잡기 위함
// ArgumentCaptor
ArgumentCaptor<Board> boardCaptor = ArgumentCaptor.forClass(Board.class);

// when
Expand Down