From 5f3c697a60efd37c9b5c77a473d42f016083bc6f Mon Sep 17 00:00:00 2001 From: soddong Date: Sun, 17 Sep 2023 20:30:29 +0900 Subject: [PATCH 1/5] Post Create --- .../application/CreatePostService.java | 19 +++++ .../application/UpdatePostService.java | 5 ++ .../controllers/PostController.java | 36 ++++++++++ .../megaptera/assignment/dto/CommentDto.java | 4 ++ .../assignment/dto/PostCreateDto.java | 31 ++++++++ .../kr/megaptera/assignment/dto/PostDto.java | 52 ++++++++++++++ .../megaptera/assignment/model/Comment.java | 4 ++ .../assignment/model/MultiLineText.java | 17 +++++ .../kr/megaptera/assignment/model/Post.java | 36 ++++++++++ .../kr/megaptera/assignment/model/PostId.java | 9 +++ .../assignment/model/SingleLineText.java | 9 +++ .../repository/CommentRepository.java | 4 ++ .../assignment/repository/PostRepository.java | 21 ++++++ .../controllers/PostControllerTest.java | 70 +++++++++++++++++-- 14 files changed, 311 insertions(+), 6 deletions(-) create mode 100644 src/main/java/kr/megaptera/assignment/dto/CommentDto.java create mode 100644 src/main/java/kr/megaptera/assignment/dto/PostCreateDto.java create mode 100644 src/main/java/kr/megaptera/assignment/dto/PostDto.java create mode 100644 src/main/java/kr/megaptera/assignment/model/Comment.java create mode 100644 src/main/java/kr/megaptera/assignment/model/MultiLineText.java create mode 100644 src/main/java/kr/megaptera/assignment/model/Post.java create mode 100644 src/main/java/kr/megaptera/assignment/model/PostId.java create mode 100644 src/main/java/kr/megaptera/assignment/model/SingleLineText.java create mode 100644 src/main/java/kr/megaptera/assignment/repository/CommentRepository.java create mode 100644 src/main/java/kr/megaptera/assignment/repository/PostRepository.java diff --git a/src/main/java/kr/megaptera/assignment/application/CreatePostService.java b/src/main/java/kr/megaptera/assignment/application/CreatePostService.java index 413a950..fc9cecf 100644 --- a/src/main/java/kr/megaptera/assignment/application/CreatePostService.java +++ b/src/main/java/kr/megaptera/assignment/application/CreatePostService.java @@ -1,4 +1,23 @@ package kr.megaptera.assignment.application; +import kr.megaptera.assignment.dto.PostCreateDto; +import kr.megaptera.assignment.dto.PostDto; +import kr.megaptera.assignment.model.Post; +import kr.megaptera.assignment.repository.PostRepository; +import org.springframework.stereotype.Service; + +@Service public class CreatePostService { + private PostRepository postRepository; + + public CreatePostService() { + this.postRepository = new PostRepository(); + } + + public PostDto createPost(PostCreateDto postCreateDto) { + Post post = new Post(postCreateDto); + postRepository.save(post); + + return new PostDto(post); + } } diff --git a/src/main/java/kr/megaptera/assignment/application/UpdatePostService.java b/src/main/java/kr/megaptera/assignment/application/UpdatePostService.java index 15dff58..009e65f 100644 --- a/src/main/java/kr/megaptera/assignment/application/UpdatePostService.java +++ b/src/main/java/kr/megaptera/assignment/application/UpdatePostService.java @@ -1,4 +1,9 @@ package kr.megaptera.assignment.application; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + public class UpdatePostService { + } diff --git a/src/main/java/kr/megaptera/assignment/controllers/PostController.java b/src/main/java/kr/megaptera/assignment/controllers/PostController.java index d088e71..b2fa783 100644 --- a/src/main/java/kr/megaptera/assignment/controllers/PostController.java +++ b/src/main/java/kr/megaptera/assignment/controllers/PostController.java @@ -1,4 +1,40 @@ package kr.megaptera.assignment.controllers; +import kr.megaptera.assignment.application.CreatePostService; +import kr.megaptera.assignment.application.DeletePostService; +import kr.megaptera.assignment.application.GetPostService; +import kr.megaptera.assignment.application.GetPostsService; +import kr.megaptera.assignment.application.UpdatePostService; +import kr.megaptera.assignment.dto.PostCreateDto; +import kr.megaptera.assignment.dto.PostDto; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@CrossOrigin +@RestController +@RequestMapping("/posts") public class PostController { + private CreatePostService createPostService; + private GetPostsService getPostsService; + private GetPostService getPostService; + private UpdatePostService updatePostService; + private DeletePostService deletePostService; + + public PostController(){ + this.createPostService = new CreatePostService(); + this.getPostsService = new GetPostsService(); + this.getPostService = new GetPostService(); + this.updatePostService = new UpdatePostService(); + this.deletePostService = new DeletePostService(); + } + + @PostMapping + public PostDto create(@RequestBody PostCreateDto postCreateDto){ + PostDto created = createPostService.createPost(postCreateDto); + return created; + } + } diff --git a/src/main/java/kr/megaptera/assignment/dto/CommentDto.java b/src/main/java/kr/megaptera/assignment/dto/CommentDto.java new file mode 100644 index 0000000..27c1d4f --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/dto/CommentDto.java @@ -0,0 +1,4 @@ +package kr.megaptera.assignment.dto; + +public class CommentDto { +} diff --git a/src/main/java/kr/megaptera/assignment/dto/PostCreateDto.java b/src/main/java/kr/megaptera/assignment/dto/PostCreateDto.java new file mode 100644 index 0000000..583b521 --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/dto/PostCreateDto.java @@ -0,0 +1,31 @@ +package kr.megaptera.assignment.dto; + +public class PostCreateDto { + private String title; + private String author; + private String comment; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } +} diff --git a/src/main/java/kr/megaptera/assignment/dto/PostDto.java b/src/main/java/kr/megaptera/assignment/dto/PostDto.java new file mode 100644 index 0000000..cac0ead --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/dto/PostDto.java @@ -0,0 +1,52 @@ +package kr.megaptera.assignment.dto; + +import kr.megaptera.assignment.model.Post; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +public class PostDto { + private String id; + private String title; + private String author; + private String comment; + + public PostDto(Post post) { + this.id = post.id().toString(); + this.title = post.title().toString(); + this.author = post.author().toString(); + this.comment = post.comment().toString(); + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getComment() { + return comment; + } + + public void setComment(String comment) { + this.comment = comment; + } + +} diff --git a/src/main/java/kr/megaptera/assignment/model/Comment.java b/src/main/java/kr/megaptera/assignment/model/Comment.java new file mode 100644 index 0000000..f639993 --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/model/Comment.java @@ -0,0 +1,4 @@ +package kr.megaptera.assignment.model; + +public class Comment { +} diff --git a/src/main/java/kr/megaptera/assignment/model/MultiLineText.java b/src/main/java/kr/megaptera/assignment/model/MultiLineText.java new file mode 100644 index 0000000..9b38f42 --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/model/MultiLineText.java @@ -0,0 +1,17 @@ +package kr.megaptera.assignment.model; + +import java.util.Arrays; +import java.util.List; + +public class MultiLineText { + private List lines; + + public MultiLineText(String text) { + this.lines = Arrays.asList(text.split("\n")); + } + + @Override + public String toString(){ + return String.join("\n", lines); + } +} diff --git a/src/main/java/kr/megaptera/assignment/model/Post.java b/src/main/java/kr/megaptera/assignment/model/Post.java new file mode 100644 index 0000000..b0ab8a5 --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/model/Post.java @@ -0,0 +1,36 @@ +package kr.megaptera.assignment.model; + +import kr.megaptera.assignment.dto.PostCreateDto; + +import java.util.UUID; + +public class Post { + private PostId id; + private SingleLineText title; + private SingleLineText author; + private MultiLineText comment; + + public Post(PostCreateDto postCreateDto){ + this.id = new PostId(UUID.randomUUID().toString()); + this.title = new SingleLineText(postCreateDto.getTitle()); + this.author = new SingleLineText(postCreateDto.getAuthor()); + this.comment = new MultiLineText(postCreateDto.getComment()); + } + + public PostId id(){ + return id; + } + + public SingleLineText title(){ + return title; + } + + public SingleLineText author(){ + return author; + } + + public MultiLineText comment(){ + return comment; + } + +} \ No newline at end of file diff --git a/src/main/java/kr/megaptera/assignment/model/PostId.java b/src/main/java/kr/megaptera/assignment/model/PostId.java new file mode 100644 index 0000000..3131bdb --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/model/PostId.java @@ -0,0 +1,9 @@ +package kr.megaptera.assignment.model; + +public class PostId { + private String id; + + public PostId(String id) { + this.id = id; + } +} diff --git a/src/main/java/kr/megaptera/assignment/model/SingleLineText.java b/src/main/java/kr/megaptera/assignment/model/SingleLineText.java new file mode 100644 index 0000000..e84d538 --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/model/SingleLineText.java @@ -0,0 +1,9 @@ +package kr.megaptera.assignment.model; + +public class SingleLineText { + private String text; + + public SingleLineText(String text) { + this.text = text; + } +} diff --git a/src/main/java/kr/megaptera/assignment/repository/CommentRepository.java b/src/main/java/kr/megaptera/assignment/repository/CommentRepository.java new file mode 100644 index 0000000..a30784b --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/repository/CommentRepository.java @@ -0,0 +1,4 @@ +package kr.megaptera.assignment.repository; + +public class CommentRepository { +} diff --git a/src/main/java/kr/megaptera/assignment/repository/PostRepository.java b/src/main/java/kr/megaptera/assignment/repository/PostRepository.java new file mode 100644 index 0000000..393c6fd --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/repository/PostRepository.java @@ -0,0 +1,21 @@ +package kr.megaptera.assignment.repository; + +import kr.megaptera.assignment.model.Post; +import kr.megaptera.assignment.model.PostId; +import org.springframework.stereotype.Repository; + +import java.util.HashMap; +import java.util.Map; + +@Repository +public class PostRepository { + private Map store; + + public PostRepository() { + this.store = new HashMap<>(); + } + + public void save(Post post) { + store.put(post.id(), post); + } +} diff --git a/src/test/java/kr/megaptera/assignment/controllers/PostControllerTest.java b/src/test/java/kr/megaptera/assignment/controllers/PostControllerTest.java index 23ed4e6..8e9c97d 100644 --- a/src/test/java/kr/megaptera/assignment/controllers/PostControllerTest.java +++ b/src/test/java/kr/megaptera/assignment/controllers/PostControllerTest.java @@ -1,36 +1,94 @@ package kr.megaptera.assignment.controllers; +import kr.megaptera.assignment.application.CreatePostService; +import kr.megaptera.assignment.application.DeletePostService; +import kr.megaptera.assignment.application.GetPostService; +import kr.megaptera.assignment.application.GetPostsService; +import kr.megaptera.assignment.application.UpdatePostService; +import kr.megaptera.assignment.dto.PostCreateDto; + 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.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.List; + +import static org.hamcrest.Matchers.containsString; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.verify; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +@WebMvcTest(PostController.class) class PostControllerTest { + @Autowired + MockMvc mockMvc; + + @MockBean + private GetPostsService getPostsService; + + @MockBean + private GetPostService getPostService; + + @MockBean + private CreatePostService createPostService; + + @MockBean + private UpdatePostService updatePostService; + + @MockBean + private DeletePostService deletePostService; + @Test @DisplayName("GET /posts") - void list() { + void list() throws Exception { } @Test @DisplayName("GET /posts/{id} - with correct ID") - void detailWithCorrectId() { + void detailWithCorrectId() throws Exception { } @Test @DisplayName("GET /posts/{id} - with incorrect ID") - void detail() { + void detail() throws Exception { } @Test @DisplayName("POST /posts") - void create() { + void create() throws Exception { + String json = """ + { + "title": "데브로드", + "author": "홀맨", + "content": "열심히 합시다" + } + """; + + mockMvc.perform(post("/posts") + .contentType(MediaType.APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isCreated()); + + verify(createPostService).createPost(any(PostCreateDto.class)); } @Test @DisplayName("PATCH /posts/{id}") - void update() { + void update() throws Exception { } @Test @DisplayName("DELETE /posts/{id}") - void deletePost() { + void deletePost() throws Exception { } } + From 7c025fe2ac793878a909ea395c1ee4f01ce505b1 Mon Sep 17 00:00:00 2001 From: soddong Date: Sun, 17 Sep 2023 22:02:43 +0900 Subject: [PATCH 2/5] Post Get --- .../application/CreatePostService.java | 15 ++++++-- .../application/GetPostService.java | 17 +++++++++ .../application/GetPostsService.java | 19 ++++++++++ .../controllers/PostController.java | 38 ++++++++++++++++--- .../assignment/dto/PostCreateDto.java | 10 ++--- .../kr/megaptera/assignment/dto/PostDto.java | 12 +++--- .../assignment/exception/PostNotFound.java | 4 ++ .../kr/megaptera/assignment/model/Post.java | 21 ++++++---- .../kr/megaptera/assignment/model/PostId.java | 23 +++++++++++ .../assignment/model/SingleLineText.java | 19 ++++++++++ .../assignment/repository/PostRepository.java | 18 +++++++++ 11 files changed, 168 insertions(+), 28 deletions(-) create mode 100644 src/main/java/kr/megaptera/assignment/exception/PostNotFound.java diff --git a/src/main/java/kr/megaptera/assignment/application/CreatePostService.java b/src/main/java/kr/megaptera/assignment/application/CreatePostService.java index fc9cecf..b1ddeef 100644 --- a/src/main/java/kr/megaptera/assignment/application/CreatePostService.java +++ b/src/main/java/kr/megaptera/assignment/application/CreatePostService.java @@ -2,20 +2,27 @@ import kr.megaptera.assignment.dto.PostCreateDto; import kr.megaptera.assignment.dto.PostDto; +import kr.megaptera.assignment.model.MultiLineText; import kr.megaptera.assignment.model.Post; +import kr.megaptera.assignment.model.SingleLineText; import kr.megaptera.assignment.repository.PostRepository; import org.springframework.stereotype.Service; +import java.util.List; + @Service public class CreatePostService { - private PostRepository postRepository; + private final PostRepository postRepository; - public CreatePostService() { - this.postRepository = new PostRepository(); + public CreatePostService(PostRepository postRepository) { + this.postRepository = postRepository; } public PostDto createPost(PostCreateDto postCreateDto) { - Post post = new Post(postCreateDto); + Post post = new Post( + new SingleLineText(postCreateDto.getTitle()), + new SingleLineText(postCreateDto.getAuthor()), + new MultiLineText(postCreateDto.getContent())); postRepository.save(post); return new PostDto(post); diff --git a/src/main/java/kr/megaptera/assignment/application/GetPostService.java b/src/main/java/kr/megaptera/assignment/application/GetPostService.java index f5d1ac0..7b51e79 100644 --- a/src/main/java/kr/megaptera/assignment/application/GetPostService.java +++ b/src/main/java/kr/megaptera/assignment/application/GetPostService.java @@ -1,4 +1,21 @@ package kr.megaptera.assignment.application; +import kr.megaptera.assignment.dto.PostDto; +import kr.megaptera.assignment.model.Post; +import kr.megaptera.assignment.model.PostId; +import kr.megaptera.assignment.repository.PostRepository; +import org.springframework.stereotype.Service; + +@Service public class GetPostService { + private final PostRepository postRepository; + + public GetPostService(PostRepository postRepository) { + this.postRepository = postRepository; + } + + public PostDto getPostDto(String id) { + Post post = postRepository.findOne(PostId.of(id)); + return new PostDto(post); + } } diff --git a/src/main/java/kr/megaptera/assignment/application/GetPostsService.java b/src/main/java/kr/megaptera/assignment/application/GetPostsService.java index a2e5905..f2cc2e0 100644 --- a/src/main/java/kr/megaptera/assignment/application/GetPostsService.java +++ b/src/main/java/kr/megaptera/assignment/application/GetPostsService.java @@ -1,4 +1,23 @@ package kr.megaptera.assignment.application; +import kr.megaptera.assignment.dto.PostDto; +import kr.megaptera.assignment.model.Post; +import kr.megaptera.assignment.repository.PostRepository; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service public class GetPostsService { + private final PostRepository postRepository; + + public GetPostsService(PostRepository postRepository) { + this.postRepository = postRepository; + } + + public List getPostDtos() { + List posts = postRepository.findAll(); + + return posts.stream().map(PostDto::new).toList(); + } } diff --git a/src/main/java/kr/megaptera/assignment/controllers/PostController.java b/src/main/java/kr/megaptera/assignment/controllers/PostController.java index b2fa783..fc79fd7 100644 --- a/src/main/java/kr/megaptera/assignment/controllers/PostController.java +++ b/src/main/java/kr/megaptera/assignment/controllers/PostController.java @@ -1,5 +1,6 @@ package kr.megaptera.assignment.controllers; +import jakarta.websocket.server.PathParam; import kr.megaptera.assignment.application.CreatePostService; import kr.megaptera.assignment.application.DeletePostService; import kr.megaptera.assignment.application.GetPostService; @@ -7,12 +8,19 @@ import kr.megaptera.assignment.application.UpdatePostService; import kr.megaptera.assignment.dto.PostCreateDto; import kr.megaptera.assignment.dto.PostDto; +import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.CrossOrigin; +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.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + @CrossOrigin @RestController @RequestMapping("/posts") @@ -23,18 +31,36 @@ public class PostController { private UpdatePostService updatePostService; private DeletePostService deletePostService; - public PostController(){ - this.createPostService = new CreatePostService(); - this.getPostsService = new GetPostsService(); - this.getPostService = new GetPostService(); - this.updatePostService = new UpdatePostService(); - this.deletePostService = new DeletePostService(); + public PostController(CreatePostService createPostService, + GetPostsService getPostsService, + GetPostService getPostService +// UpdatePostService updatePostService, +// DeletePostService deletePostService + ) { + this.createPostService = createPostService; + this.getPostsService = getPostsService; + this.getPostService = getPostService; +// this.updatePostService = updatePostService; +// this.deletePostService = deletePostService; } @PostMapping + @ResponseStatus(HttpStatus.CREATED) public PostDto create(@RequestBody PostCreateDto postCreateDto){ PostDto created = createPostService.createPost(postCreateDto); return created; } + @GetMapping + public List getLists(){ + List postDtos = getPostsService.getPostDtos(); + return postDtos; + } + + @GetMapping("/{id}") + public PostDto getDetail(@PathVariable String id){ + PostDto postDto = getPostService.getPostDto(id); + return postDto; + } + } diff --git a/src/main/java/kr/megaptera/assignment/dto/PostCreateDto.java b/src/main/java/kr/megaptera/assignment/dto/PostCreateDto.java index 583b521..a1674b2 100644 --- a/src/main/java/kr/megaptera/assignment/dto/PostCreateDto.java +++ b/src/main/java/kr/megaptera/assignment/dto/PostCreateDto.java @@ -3,7 +3,7 @@ public class PostCreateDto { private String title; private String author; - private String comment; + private String content; public String getTitle() { return title; @@ -21,11 +21,11 @@ public void setAuthor(String author) { this.author = author; } - public String getComment() { - return comment; + public String getContent() { + return content; } - public void setComment(String comment) { - this.comment = comment; + public void setContent(String content) { + this.content = content; } } diff --git a/src/main/java/kr/megaptera/assignment/dto/PostDto.java b/src/main/java/kr/megaptera/assignment/dto/PostDto.java index cac0ead..77bc2d9 100644 --- a/src/main/java/kr/megaptera/assignment/dto/PostDto.java +++ b/src/main/java/kr/megaptera/assignment/dto/PostDto.java @@ -8,13 +8,13 @@ public class PostDto { private String id; private String title; private String author; - private String comment; + private String content; public PostDto(Post post) { this.id = post.id().toString(); this.title = post.title().toString(); this.author = post.author().toString(); - this.comment = post.comment().toString(); + this.content = post.content().toString(); } public String getId() { @@ -41,12 +41,12 @@ public void setAuthor(String author) { this.author = author; } - public String getComment() { - return comment; + public String getContent() { + return content; } - public void setComment(String comment) { - this.comment = comment; + public void setContent(String comment) { + this.content = content; } } diff --git a/src/main/java/kr/megaptera/assignment/exception/PostNotFound.java b/src/main/java/kr/megaptera/assignment/exception/PostNotFound.java new file mode 100644 index 0000000..5467c90 --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/exception/PostNotFound.java @@ -0,0 +1,4 @@ +package kr.megaptera.assignment.exception; + +public class PostNotFound extends RuntimeException { +} diff --git a/src/main/java/kr/megaptera/assignment/model/Post.java b/src/main/java/kr/megaptera/assignment/model/Post.java index b0ab8a5..39ab47b 100644 --- a/src/main/java/kr/megaptera/assignment/model/Post.java +++ b/src/main/java/kr/megaptera/assignment/model/Post.java @@ -8,13 +8,20 @@ public class Post { private PostId id; private SingleLineText title; private SingleLineText author; - private MultiLineText comment; + private MultiLineText content; - public Post(PostCreateDto postCreateDto){ + public Post(PostId id, SingleLineText title, SingleLineText author, MultiLineText content){ + this.id = id; + this.title = title; + this.author = author; + this.content = content; + } + + public Post(SingleLineText title, SingleLineText author, MultiLineText content){ this.id = new PostId(UUID.randomUUID().toString()); - this.title = new SingleLineText(postCreateDto.getTitle()); - this.author = new SingleLineText(postCreateDto.getAuthor()); - this.comment = new MultiLineText(postCreateDto.getComment()); + this.title = title; + this.author = author; + this.content = content; } public PostId id(){ @@ -29,8 +36,8 @@ public SingleLineText author(){ return author; } - public MultiLineText comment(){ - return comment; + public MultiLineText content(){ + return content; } } \ No newline at end of file diff --git a/src/main/java/kr/megaptera/assignment/model/PostId.java b/src/main/java/kr/megaptera/assignment/model/PostId.java index 3131bdb..a1ee63f 100644 --- a/src/main/java/kr/megaptera/assignment/model/PostId.java +++ b/src/main/java/kr/megaptera/assignment/model/PostId.java @@ -1,9 +1,32 @@ package kr.megaptera.assignment.model; +import java.util.Objects; + public class PostId { private String id; public PostId(String id) { this.id = id; } + + @Override + public String toString(){ + return id; + } + + public static PostId of(String id){ + return new PostId(id); + } + + @Override + public boolean equals(Object other) { + PostId otherPostId = (PostId) other; + + return Objects.equals(id, otherPostId.id); + } + + @Override + public int hashCode() { + return Objects.hash(id); + } } diff --git a/src/main/java/kr/megaptera/assignment/model/SingleLineText.java b/src/main/java/kr/megaptera/assignment/model/SingleLineText.java index e84d538..bacd9e9 100644 --- a/src/main/java/kr/megaptera/assignment/model/SingleLineText.java +++ b/src/main/java/kr/megaptera/assignment/model/SingleLineText.java @@ -1,9 +1,28 @@ package kr.megaptera.assignment.model; +import java.util.Objects; + public class SingleLineText { private String text; public SingleLineText(String text) { this.text = text; } + + @Override + public String toString(){ + return text; + } + + @Override + public boolean equals(Object other) { + SingleLineText otherPostId = (SingleLineText) other; + + return Objects.equals(text, otherPostId.text); + } + + @Override + public int hashCode() { + return Objects.hash(text); + } } diff --git a/src/main/java/kr/megaptera/assignment/repository/PostRepository.java b/src/main/java/kr/megaptera/assignment/repository/PostRepository.java index 393c6fd..278ff98 100644 --- a/src/main/java/kr/megaptera/assignment/repository/PostRepository.java +++ b/src/main/java/kr/megaptera/assignment/repository/PostRepository.java @@ -1,10 +1,14 @@ package kr.megaptera.assignment.repository; +import kr.megaptera.assignment.dto.PostDto; +import kr.megaptera.assignment.exception.PostNotFound; import kr.megaptera.assignment.model.Post; import kr.megaptera.assignment.model.PostId; import org.springframework.stereotype.Repository; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; @Repository @@ -18,4 +22,18 @@ public PostRepository() { public void save(Post post) { store.put(post.id(), post); } + + public List findAll() { + return new ArrayList<>(store.values()); + } + + public Post findOne(PostId id) { + Post post = store.get(id); + + if (post == null) { + throw new PostNotFound(); + } + + return post; + } } From 7c2d1d3a06d5347c35ac1f233b5dfa106c78b441 Mon Sep 17 00:00:00 2001 From: soddong Date: Sun, 17 Sep 2023 22:29:38 +0900 Subject: [PATCH 3/5] Post Patch --- .../application/UpdatePostService.java | 27 ++++++++++++++++--- .../controllers/PostController.java | 16 ++++++++--- .../assignment/dto/PostUpdateDto.java | 22 +++++++++++++++ .../kr/megaptera/assignment/model/Post.java | 4 +++ 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 src/main/java/kr/megaptera/assignment/dto/PostUpdateDto.java diff --git a/src/main/java/kr/megaptera/assignment/application/UpdatePostService.java b/src/main/java/kr/megaptera/assignment/application/UpdatePostService.java index 009e65f..1be50b2 100644 --- a/src/main/java/kr/megaptera/assignment/application/UpdatePostService.java +++ b/src/main/java/kr/megaptera/assignment/application/UpdatePostService.java @@ -1,9 +1,30 @@ package kr.megaptera.assignment.application; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import kr.megaptera.assignment.dto.PostDto; +import kr.megaptera.assignment.dto.PostUpdateDto; +import kr.megaptera.assignment.model.MultiLineText; +import kr.megaptera.assignment.model.Post; +import kr.megaptera.assignment.model.PostId; +import kr.megaptera.assignment.model.SingleLineText; +import kr.megaptera.assignment.repository.PostRepository; +import org.springframework.stereotype.Service; +@Service public class UpdatePostService { + private final PostRepository postRepository; + + public UpdatePostService(PostRepository postRepository) { + this.postRepository = postRepository; + } + + public PostDto updatePost(PostUpdateDto postUpdateDto, String id) { + Post post = postRepository.findOne(PostId.of(id)); + post.update( + new SingleLineText(postUpdateDto.getTitle()), + new MultiLineText(postUpdateDto.getContent()) + ); + + return new PostDto(post); + } } diff --git a/src/main/java/kr/megaptera/assignment/controllers/PostController.java b/src/main/java/kr/megaptera/assignment/controllers/PostController.java index fc79fd7..b5ea867 100644 --- a/src/main/java/kr/megaptera/assignment/controllers/PostController.java +++ b/src/main/java/kr/megaptera/assignment/controllers/PostController.java @@ -8,9 +8,11 @@ import kr.megaptera.assignment.application.UpdatePostService; import kr.megaptera.assignment.dto.PostCreateDto; import kr.megaptera.assignment.dto.PostDto; +import kr.megaptera.assignment.dto.PostUpdateDto; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -33,14 +35,14 @@ public class PostController { public PostController(CreatePostService createPostService, GetPostsService getPostsService, - GetPostService getPostService -// UpdatePostService updatePostService, + GetPostService getPostService, + UpdatePostService updatePostService // DeletePostService deletePostService ) { this.createPostService = createPostService; this.getPostsService = getPostsService; this.getPostService = getPostService; -// this.updatePostService = updatePostService; + this.updatePostService = updatePostService; // this.deletePostService = deletePostService; } @@ -63,4 +65,12 @@ public PostDto getDetail(@PathVariable String id){ return postDto; } + @PatchMapping("/{id}") + public PostDto update(@PathVariable String id, + @RequestBody PostUpdateDto postUpdateDto){ + PostDto updated = updatePostService.updatePost(postUpdateDto, id); + + return updated; + } + } diff --git a/src/main/java/kr/megaptera/assignment/dto/PostUpdateDto.java b/src/main/java/kr/megaptera/assignment/dto/PostUpdateDto.java new file mode 100644 index 0000000..23a968b --- /dev/null +++ b/src/main/java/kr/megaptera/assignment/dto/PostUpdateDto.java @@ -0,0 +1,22 @@ +package kr.megaptera.assignment.dto; + +public class PostUpdateDto { + private String title; + private String content; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/src/main/java/kr/megaptera/assignment/model/Post.java b/src/main/java/kr/megaptera/assignment/model/Post.java index 39ab47b..93fb505 100644 --- a/src/main/java/kr/megaptera/assignment/model/Post.java +++ b/src/main/java/kr/megaptera/assignment/model/Post.java @@ -40,4 +40,8 @@ public MultiLineText content(){ return content; } + public void update(SingleLineText title, MultiLineText content) { + this.title = title; + this.content = content; + } } \ No newline at end of file From bd2cf799ba8e5cf63cff995fbb1d987e5a3fc21a Mon Sep 17 00:00:00 2001 From: soddong Date: Sun, 17 Sep 2023 22:40:57 +0900 Subject: [PATCH 4/5] Post Delete --- .../application/DeletePostService.java | 17 +++++++++++++++++ .../assignment/controllers/PostController.java | 14 +++++++++++--- .../assignment/repository/PostRepository.java | 6 ++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/main/java/kr/megaptera/assignment/application/DeletePostService.java b/src/main/java/kr/megaptera/assignment/application/DeletePostService.java index e656f51..16544f4 100644 --- a/src/main/java/kr/megaptera/assignment/application/DeletePostService.java +++ b/src/main/java/kr/megaptera/assignment/application/DeletePostService.java @@ -1,4 +1,21 @@ package kr.megaptera.assignment.application; +import kr.megaptera.assignment.dto.PostDto; +import kr.megaptera.assignment.model.Post; +import kr.megaptera.assignment.model.PostId; +import kr.megaptera.assignment.repository.PostRepository; +import org.springframework.stereotype.Service; + +@Service public class DeletePostService { + private final PostRepository postRepository; + + public DeletePostService(PostRepository postRepository) { + this.postRepository = postRepository; + } + + public PostDto deletePost(String id) { + Post post = postRepository.remove(PostId.of(id)); + return new PostDto(post); + } } diff --git a/src/main/java/kr/megaptera/assignment/controllers/PostController.java b/src/main/java/kr/megaptera/assignment/controllers/PostController.java index b5ea867..53aa32a 100644 --- a/src/main/java/kr/megaptera/assignment/controllers/PostController.java +++ b/src/main/java/kr/megaptera/assignment/controllers/PostController.java @@ -11,6 +11,7 @@ import kr.megaptera.assignment.dto.PostUpdateDto; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -36,14 +37,14 @@ public class PostController { public PostController(CreatePostService createPostService, GetPostsService getPostsService, GetPostService getPostService, - UpdatePostService updatePostService -// DeletePostService deletePostService + UpdatePostService updatePostService, + DeletePostService deletePostService ) { this.createPostService = createPostService; this.getPostsService = getPostsService; this.getPostService = getPostService; this.updatePostService = updatePostService; -// this.deletePostService = deletePostService; + this.deletePostService = deletePostService; } @PostMapping @@ -73,4 +74,11 @@ public PostDto update(@PathVariable String id, return updated; } + @DeleteMapping("/{id}") + public PostDto delete(@PathVariable String id){ + PostDto postDto = deletePostService.deletePost(id); + + return postDto; + } + } diff --git a/src/main/java/kr/megaptera/assignment/repository/PostRepository.java b/src/main/java/kr/megaptera/assignment/repository/PostRepository.java index 278ff98..6910960 100644 --- a/src/main/java/kr/megaptera/assignment/repository/PostRepository.java +++ b/src/main/java/kr/megaptera/assignment/repository/PostRepository.java @@ -36,4 +36,10 @@ public Post findOne(PostId id) { return post; } + + public Post remove(PostId id) { + Post post = store.remove(id); + + return post; + } } From 2c041d48405ecfdf07f5a12ad3b29fd5c8006558 Mon Sep 17 00:00:00 2001 From: soddong Date: Sun, 17 Sep 2023 23:05:36 +0900 Subject: [PATCH 5/5] Post test --- .../kr/megaptera/assignment/dto/PostDto.java | 7 +++ .../controllers/PostControllerTest.java | 55 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/main/java/kr/megaptera/assignment/dto/PostDto.java b/src/main/java/kr/megaptera/assignment/dto/PostDto.java index 77bc2d9..cf465cf 100644 --- a/src/main/java/kr/megaptera/assignment/dto/PostDto.java +++ b/src/main/java/kr/megaptera/assignment/dto/PostDto.java @@ -17,6 +17,13 @@ public PostDto(Post post) { this.content = post.content().toString(); } + public PostDto(String id, String title, String author, String content) { + this.id = id; + this.title = title; + this.author = author; + this.content = content; + } + public String getId() { return id; } diff --git a/src/test/java/kr/megaptera/assignment/controllers/PostControllerTest.java b/src/test/java/kr/megaptera/assignment/controllers/PostControllerTest.java index 8e9c97d..5ee4746 100644 --- a/src/test/java/kr/megaptera/assignment/controllers/PostControllerTest.java +++ b/src/test/java/kr/megaptera/assignment/controllers/PostControllerTest.java @@ -7,6 +7,9 @@ import kr.megaptera.assignment.application.UpdatePostService; import kr.megaptera.assignment.dto.PostCreateDto; +import kr.megaptera.assignment.dto.PostDto; +import kr.megaptera.assignment.dto.PostUpdateDto; +import kr.megaptera.assignment.exception.PostNotFound; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -21,6 +24,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @@ -49,16 +53,44 @@ class PostControllerTest { @Test @DisplayName("GET /posts") void list() throws Exception { + given(getPostsService.getPostDtos()).willReturn(List.of( + new PostDto("001", "title1", "작성자1", "내용1"), + new PostDto("002", "제목2", "작성자2", "내용2") + )); + + mockMvc.perform(get("/posts")) + .andExpect(status().isOk()) + .andExpect(content().string( + containsString("title1") + )); } + @Test @DisplayName("GET /posts/{id} - with correct ID") void detailWithCorrectId() throws Exception { + String id = "001POST"; + + given(getPostService.getPostDto(id)) + .willReturn(new PostDto(id, "title", "작성자", "내용")); + + mockMvc.perform(get("/posts/" + id)) + .andExpect(status().isOk()) + .andExpect(content().string( + containsString("title") + )); } @Test @DisplayName("GET /posts/{id} - with incorrect ID") void detail() throws Exception { + String id = "999POST"; + + given(getPostService.getPostDto(id)) + .willThrow(new PostNotFound()); + + mockMvc.perform(get("/posts/" + id)) + .andExpect(status().isNotFound()); } @Test @@ -84,11 +116,34 @@ void create() throws Exception { @Test @DisplayName("PATCH /posts/{id}") void update() throws Exception { + String id = "001POST"; + + String json = """ + { + "title": "데브로드", + "content": "열심히 합시다" + } + """; + + mockMvc.perform(patch("/posts/" + id) + .contentType(MediaType.APPLICATION_JSON) + .content(json) + ) + .andExpect(status().isOk()); + + verify(updatePostService) + .updatePost(eq(id), any(PostUpdateDto.class)); } @Test @DisplayName("DELETE /posts/{id}") void deletePost() throws Exception { + String id = "001POST"; + + mockMvc.perform(delete("/posts/" + id)) + .andExpect(status().isOk()); + + verify(deletePostService).deletePost(id); } }