Skip to content
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

feat: 독서록 조회 기능 컨트롤러 로직 작성 #21

Merged
merged 5 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions src/main/java/com/inmybook/adapter/in/web/PostController.java
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
package com.inmybook.adapter.in.web;

import static com.inmybook.adapter.in.web.dto.PostMapper.*;

import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import com.inmybook.adapter.in.web.dto.PostMapper;
import com.inmybook.adapter.in.web.dto.RegisterPostInput;
import com.inmybook.adapter.in.web.dto.response.PostDetailsResponse;
import com.inmybook.application.port.in.ReadPostInput;
import com.inmybook.application.port.in.ReadPostUseCase;
import com.inmybook.application.port.in.RegisterPostCommand;
import com.inmybook.application.port.in.RegisterPostUseCase;
import com.inmybook.application.service.PostDetailsOutput;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand All @@ -24,7 +31,7 @@
public class PostController {

private final RegisterPostUseCase registerPostUseCase;
private final PostMapper postMapper;
private final ReadPostUseCase readPostUseCase;

@Operation(summary = "독서록 게시글 등록", description = "사용자는 독서록 게시글을 등록할 수 있다.")
@ApiResponse(
Expand All @@ -34,11 +41,24 @@ public class PostController {
public ResponseEntity<String> registerPost(@RequestPart RegisterPostInput registerPostInput,
@RequestPart(value = "uploadImg", required = false) MultipartFile multipartFile) {

RegisterPostCommand registerPostCommand = postMapper.createRegisterPostCommand(registerPostInput,
RegisterPostCommand registerPostCommand = createRegisterPostCommand(registerPostInput,
multipartFile);
String path = registerPostUseCase.registerPost(registerPostCommand);

return new ResponseEntity<>(path, HttpStatus.CREATED);
}

@Operation(summary = "독서록 책 정보 조회", description = "사용자는 독서록 게시글을 조회할 수 있다.")
@ApiResponse(
responseCode = "200", description = "독서록 게시글 조회 성공"
)
@GetMapping(value = "/posts/{postId}")
public ResponseEntity<PostDetailsResponse> getContent(@PathVariable String postId) {
ReadPostInput readPostInput = new ReadPostInput(postId);
PostDetailsOutput postDetailsOutput = readPostUseCase.findPostById(readPostInput);

PostDetailsResponse postDetailsResponse = createReadPostDetailsResponse(postDetailsOutput);

return new ResponseEntity<>(postDetailsResponse, HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
public record ContentRequest(
String title,
String content,
String fromDate,
String toDate,
String readingStartDate,
String readingEndDate,
double rating,
String isPublic
) {
Expand Down
39 changes: 32 additions & 7 deletions src/main/java/com/inmybook/adapter/in/web/dto/PostMapper.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,54 @@
package com.inmybook.adapter.in.web.dto;

import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.inmybook.adapter.in.web.dto.response.ContentResponse;
import com.inmybook.adapter.in.web.dto.response.MemberResponse;
import com.inmybook.adapter.in.web.dto.response.PostDetailsResponse;
import com.inmybook.application.port.in.RegisterPostCommand;
import com.inmybook.application.service.PostDetailsOutput;

@Component
public class PostMapper {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mapper 는 왜 component 로 주입 하나요???

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

작성 당시 단순히 빈 등록을 위해 @component를 사용했던 것 같습니다; 주입 방식을 달리 하는게 좋을까요?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static 함수로 만드는 방법도 고려해 보시면 좋을것 같아요.

public RegisterPostCommand createRegisterPostCommand(RegisterPostInput registerPostInput,
public static RegisterPostCommand createRegisterPostCommand(RegisterPostInput registerPostInput,
MultipartFile multipartFile) {
RegisterPostCommand registerPostCommand = RegisterPostCommand.builder()

return RegisterPostCommand.builder()
.isbnNo(registerPostInput.book().isbnNo())
.bookName(registerPostInput.book().bookName())
.author(registerPostInput.book().author())
.publisher(registerPostInput.book().publisher())
.title(registerPostInput.content().title())
.content(registerPostInput.content().content())
.fromDate(registerPostInput.content().fromDate())
.toDate(registerPostInput.content().toDate())
.readingStartDate(registerPostInput.content().readingStartDate())
.readingEndDate(registerPostInput.content().readingEndDate())
.rating(registerPostInput.content().rating())
.isPublic(registerPostInput.content().isPublic())
.memberId(registerPostInput.member().memberId())
.thumbnailImg(multipartFile)
.build();
}

public static PostDetailsResponse createReadPostDetailsResponse(PostDetailsOutput postDetailsOutput) {
ContentResponse contentResponse = new ContentResponse(
postDetailsOutput.contentDetailsOutput().title(),
postDetailsOutput.contentDetailsOutput().content(),
postDetailsOutput.contentDetailsOutput().readingStartDate(),
postDetailsOutput.contentDetailsOutput().readingEndDate(),
postDetailsOutput.contentDetailsOutput().rating(),
postDetailsOutput.contentDetailsOutput().likeCount(),
postDetailsOutput.contentDetailsOutput().bookmarkCount(),
postDetailsOutput.contentDetailsOutput().isPublic()
);

MemberResponse memberResponse = new MemberResponse(
postDetailsOutput.memberDetailsOutput().memberId(),
postDetailsOutput.memberDetailsOutput().nickname()
);

return registerPostCommand;
return new PostDetailsResponse(
postDetailsOutput.postId(),
contentResponse,
memberResponse
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.inmybook.adapter.in.web.dto.response;

public record BookResponse(
String isbnNo,
String bookName,
String author,
String publisher
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.inmybook.adapter.in.web.dto.response;

public record ContentResponse(
String title,
String content,
String fromDate,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fromDate, toDate 가 무슨 뜻인가요???

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

독서 기간에 대한 변수로 각각 시작일, 종료일을 뜻하는데요. startDate, endDate로 변경하는 쪽이 더 의미가 맞다고 생각되어서 수정하려 합니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

변수명이 명확하지 않아요.

String toDate,
double rating,
int likeCount,
int bookmarkCount,
String isPublic
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.inmybook.adapter.in.web.dto.response;

public record MemberResponse(
String memberId,
String nickname
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.inmybook.adapter.in.web.dto.response;

public record PostDetailsResponse(
String postId,
ContentResponse contentResponse,
MemberResponse memberResponse
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public record RegisterPostCommand(
@NotNull
String title,
String content,
String fromDate,
String toDate,
String readingStartDate,
String readingEndDate,
double rating,
String isPublic,
@NotNull
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
public record ContentDetailsOutput(
String title,
String content,
String fromDate,
String toDate,
String readingStartDate,
String readingEndDate,
double rating,
int likeCount,
int bookmarkCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public PostDetailsOutput findPostById(ReadPostInput readPostInput) {
ContentDetailsOutput contentDetailsOutput = ContentDetailsOutput.builder()
.title(post.getContent().getTitle())
.content(post.getContent().getContent())
.fromDate(post.getContent().getFromDate())
.toDate(post.getContent().getToDate())
.readingStartDate(post.getContent().getReadingStartDate())
.readingEndDate(post.getContent().getReadingEndDate())
.rating(post.getContent().getRating())
.likeCount(post.getContent().getLikeCount())
.bookmarkCount(post.getContent().getBookmarkCount())
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/inmybook/domain/post/Content.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
public class Content {
private String title;
private String content;
private String fromDate;
private String toDate;
private String readingStartDate;
private String readingEndDate;
@Builder.Default
private double rating = 0;
@Builder.Default
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/inmybook/domain/post/PostFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ public Post createPost(RegisterPostCommand registerPostCommand) {
Content content = Content.builder()
.title(registerPostCommand.title())
.content(registerPostCommand.content())
.fromDate(registerPostCommand.fromDate())
.toDate(registerPostCommand.toDate())
.readingStartDate(registerPostCommand.readingStartDate())
.readingEndDate(registerPostCommand.readingEndDate())
.rating(registerPostCommand.rating())
.likeCount(0)
.bookmarkCount(0)
Expand Down
115 changes: 115 additions & 0 deletions src/test/java/com/inmybook/adapter/in/web/PostControllerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package com.inmybook.adapter.in.web;

import static com.inmybook.adapter.in.web.dto.PostMapper.*;
import static org.assertj.core.api.Assertions.*;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.nio.charset.StandardCharsets;
import java.util.UUID;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.ResultActions;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.inmybook.adapter.in.web.dto.PostMapper;
import com.inmybook.adapter.in.web.dto.response.PostDetailsResponse;
import com.inmybook.application.port.in.ReadPostInput;
import com.inmybook.application.port.in.ReadPostUseCase;
import com.inmybook.application.service.ContentDetailsOutput;
import com.inmybook.application.service.MemberDetailsOutput;
import com.inmybook.application.service.PostDetailsOutput;

@ExtendWith(MockitoExtension.class)
class PostControllerTest {

@InjectMocks
PostController postController;
@Mock
ReadPostUseCase readPostUseCase;

private MockMvc mockMvc;
private final ObjectMapper objectMapper = new ObjectMapper();

@BeforeEach
public void init() {
mockMvc = MockMvcBuilders.standaloneSetup(postController).build();
}

@Test
@DisplayName("사용자는 독서록 게시글을 조회할 수 있다.")
void readPost() throws Exception {
PostDetailsOutput mockPostDetailsOutput = getPostDetailsOutput();
PostDetailsResponse mockPostDetailsResponse = getPostDetailsResponse(mockPostDetailsOutput);
String postId = mockPostDetailsOutput.postId();

try (MockedStatic<PostMapper> mockPostMapper = mockStatic(PostMapper.class)) {
when(readPostUseCase.findPostById(new ReadPostInput(postId))).thenReturn(mockPostDetailsOutput);
mockPostMapper.when(() -> createReadPostDetailsResponse(mockPostDetailsOutput)).thenReturn(
mockPostDetailsResponse);

ResultActions resultActions = mockMvc.perform(get("/posts/{postId}", postId)
.contentType(MediaType.APPLICATION_JSON)
.characterEncoding("utf-8")
.content(postId)
);

MvcResult mvcResult = resultActions.andExpect(status().isOk()).andReturn();

PostDetailsResponse postDetailsResponse = objectMapper.readValue(mvcResult.getResponse().getContentAsString(
StandardCharsets.UTF_8), PostDetailsResponse.class);

assertThat(postDetailsResponse.postId()).isEqualTo(postId);
assertThat(postDetailsResponse.contentResponse().title()).isEqualTo("HTTP 완벽 가이드 독서록");
}

}

private PostDetailsResponse getPostDetailsResponse(PostDetailsOutput postDetailsOutput) {
return createReadPostDetailsResponse(postDetailsOutput);
}

private PostDetailsOutput getPostDetailsOutput() {
String postId = getUuid();

ContentDetailsOutput contentDetailsOutput = new ContentDetailsOutput(
"HTTP 완벽 가이드 독서록",
"유익합니다.",
"2024-07-14",
"2024-07-21",
4.5,
0,
0,
"Y"
);

MemberDetailsOutput memberDetailsOutput = new MemberDetailsOutput(
0L,
"dani820",
"dani820"
);

return new PostDetailsOutput(
postId,
contentDetailsOutput,
memberDetailsOutput
);
}

private String getUuid() {
return UUID.randomUUID().toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ void readPost() {
Content content = Content.builder()
.title("HTTP 완벽 가이드 독서록")
.content("유익합니다.")
.fromDate("2024-07-14")
.toDate("2024-07-21")
.readingStartDate("2024-07-14")
.readingEndDate("2024-07-21")
.rating(4.5)
.likeCount(0)
.bookmarkCount(0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ void registerPostWithUploadImgTest() {
.publisher("인사이트")
.title("HTTP 완벽 가이드 독서록")
.content("유익합니다.")
.fromDate("2024-07-14")
.toDate("2024-07-21")
.readingStartDate("2024-07-14")
.readingEndDate("2024-07-21")
.rating(4.5)
.isPublic("Y")
.memberId("dani820")
Expand Down Expand Up @@ -76,8 +76,8 @@ void registerPostWithoutUploadImgTest() {
.publisher("인사이트")
.title("HTTP 완벽 가이드 독서록")
.content("유익합니다.")
.fromDate("2024-07-14")
.toDate("2024-07-21")
.readingStartDate("2024-07-14")
.readingEndDate("2024-07-21")
.rating(4.5)
.isPublic("Y")
.memberId("dani820")
Expand Down
Loading