Skip to content

Commit

Permalink
Merge pull request #21 from f-lab-edu/feature/17
Browse files Browse the repository at this point in the history
feat: 독서록 조회 기능 컨트롤러 로직 작성
  • Loading branch information
dani820 authored Sep 20, 2024
2 parents 2099914 + cc0a5dd commit f15d005
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 8 deletions.
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);
}
}
35 changes: 30 additions & 5 deletions src/main/java/com/inmybook/adapter/in/web/dto/PostMapper.java
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
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 {
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())
Expand All @@ -23,7 +26,29 @@ public RegisterPostCommand createRegisterPostCommand(RegisterPostInput registerP
.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,
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
) {
}
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();
}

}

0 comments on commit f15d005

Please sign in to comment.