From 6d288436dc462e97cb7bd52e0b7604d43ca0440a Mon Sep 17 00:00:00 2001 From: so3500 Date: Sun, 30 Aug 2020 00:55:14 +0900 Subject: [PATCH 1/3] =?UTF-8?q?fix:=20JpaAuditing=20=EC=A0=81=EC=9A=A9=20?= =?UTF-8?q?=EC=95=88=EB=90=98=EB=8A=94=20=EB=AC=B8=EC=A0=9C=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 연관 commit 참고 https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#auditing --- src/main/java/web/chat/backend/entity/Message.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/web/chat/backend/entity/Message.java b/src/main/java/web/chat/backend/entity/Message.java index 0e1df51..2b2861d 100644 --- a/src/main/java/web/chat/backend/entity/Message.java +++ b/src/main/java/web/chat/backend/entity/Message.java @@ -4,6 +4,7 @@ import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.EntityListeners; import javax.persistence.EnumType; import javax.persistence.Enumerated; import javax.persistence.GeneratedValue; @@ -13,6 +14,7 @@ import javax.persistence.ManyToOne; import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; import lombok.Getter; import lombok.Setter; @@ -20,6 +22,7 @@ @Getter @Setter @Entity +@EntityListeners(AuditingEntityListener.class) public class Message { @Id From 3e4bfea7369d8c16548eb3481e5cae951e8c0ecd Mon Sep 17 00:00:00 2001 From: so3500 Date: Sun, 30 Aug 2020 00:57:36 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20=EB=A9=94=EC=8B=9C=EC=A7=80=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=20api=20=EA=B5=AC=ED=98=84(+=20tc)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../backend/controller/RoomController.java | 14 +++++ .../controller/request/MessageRequest.java | 10 ++++ .../chat/backend/service/MessageService.java | 7 +++ .../web/chat/backend/service/RoomService.java | 6 ++ .../controller/MessageCreationTest.java | 52 +++++++++++++++++ .../controller/RoomControllerTest.java | 56 ++++++++++++++++++- .../repository/MessageRepositoryTest.java | 47 ++++++++++++++++ 7 files changed, 191 insertions(+), 1 deletion(-) create mode 100644 src/test/java/web/chat/backend/controller/MessageCreationTest.java create mode 100644 src/test/java/web/chat/backend/repository/MessageRepositoryTest.java diff --git a/src/main/java/web/chat/backend/controller/RoomController.java b/src/main/java/web/chat/backend/controller/RoomController.java index c2adcd3..8d66f8a 100644 --- a/src/main/java/web/chat/backend/controller/RoomController.java +++ b/src/main/java/web/chat/backend/controller/RoomController.java @@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.RestController; import lombok.RequiredArgsConstructor; +import web.chat.backend.controller.request.MessageRequest; import web.chat.backend.controller.request.RoomRequest; import web.chat.backend.controller.response.MessageResponse; import web.chat.backend.controller.response.RoomResponse; @@ -52,6 +53,19 @@ public List getMessages(@PathVariable Long id) { return messages.stream().collect(new MessageCollector()); } + @PostMapping("/{roomId}/messages") + @ResponseStatus(HttpStatus.CREATED) + public MessageResponse createMessage(@PathVariable Long roomId, @RequestBody @Valid MessageRequest messageRequest) { + Message message = new Message(); + message.setContents(messageRequest.getContents()); + + Room room = roomService.getOrThrow(roomId); + + Message savedMessage = messageService.createMessage(room, message); + + return new MessageResponse(savedMessage); + } + @PostMapping("") @ResponseStatus(HttpStatus.CREATED) public RoomResponse createRoom(@RequestBody @Valid RoomRequest roomRequest) { diff --git a/src/main/java/web/chat/backend/controller/request/MessageRequest.java b/src/main/java/web/chat/backend/controller/request/MessageRequest.java index d72713c..2f6d9e1 100644 --- a/src/main/java/web/chat/backend/controller/request/MessageRequest.java +++ b/src/main/java/web/chat/backend/controller/request/MessageRequest.java @@ -1,4 +1,14 @@ package web.chat.backend.controller.request; +import javax.validation.constraints.Size; + +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter public class MessageRequest { + + @Size(min = 1) + private String contents; } diff --git a/src/main/java/web/chat/backend/service/MessageService.java b/src/main/java/web/chat/backend/service/MessageService.java index a64d7c2..3f2aed9 100644 --- a/src/main/java/web/chat/backend/service/MessageService.java +++ b/src/main/java/web/chat/backend/service/MessageService.java @@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor; import web.chat.backend.entity.Message; +import web.chat.backend.entity.Room; import web.chat.backend.exception.NotFoundException; import web.chat.backend.repository.MessageRepository; @@ -21,4 +22,10 @@ public List getMessagesBy(Long roomId) { return messageRepository.findAllByRoomId(roomId); } + + public Message createMessage(Room room, Message message) { + message.setRoom(room); + + return messageRepository.save(message); + } } diff --git a/src/main/java/web/chat/backend/service/RoomService.java b/src/main/java/web/chat/backend/service/RoomService.java index f9189fc..fd5e911 100644 --- a/src/main/java/web/chat/backend/service/RoomService.java +++ b/src/main/java/web/chat/backend/service/RoomService.java @@ -6,6 +6,7 @@ import lombok.RequiredArgsConstructor; import web.chat.backend.entity.Room; +import web.chat.backend.exception.NotFoundException; import web.chat.backend.repository.RoomRepository; @RequiredArgsConstructor @@ -21,4 +22,9 @@ public Room createRoom(Room room) { public List getRooms() { return roomRepository.findAll(); } + + public Room getOrThrow(Long roomId) { + return roomRepository.findById(roomId) + .orElseThrow(() -> new NotFoundException(String.format("Room [id:%d] not found", roomId))); + } } diff --git a/src/test/java/web/chat/backend/controller/MessageCreationTest.java b/src/test/java/web/chat/backend/controller/MessageCreationTest.java new file mode 100644 index 0000000..39c26e7 --- /dev/null +++ b/src/test/java/web/chat/backend/controller/MessageCreationTest.java @@ -0,0 +1,52 @@ +package web.chat.backend.controller; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.TestConstructor; +import org.springframework.test.context.jdbc.Sql; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; + +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.RequiredArgsConstructor; +import web.chat.backend.controller.request.MessageRequest; + +@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL) +@RequiredArgsConstructor +@AutoConfigureMockMvc +@SpringBootTest +public class MessageCreationTest { + + final MockMvc mockMvc; + final ObjectMapper objectMapper; + + final RoomController roomController; + + @Test + @Sql("/test-sql/messages.sql") + void createMessage() throws Exception { + + // given + MessageRequest req = new MessageRequest(); + req.setContents("hi hello"); + + final String body = objectMapper.writeValueAsString(req); + + // when + ResultActions action = mockMvc.perform( + post("/api/rooms/{roomId}/messages", 1) + .contentType(MediaType.APPLICATION_JSON) + .content(body)); + + // then + action.andDo(print()) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.contents").value(req.getContents())); + } +} diff --git a/src/test/java/web/chat/backend/controller/RoomControllerTest.java b/src/test/java/web/chat/backend/controller/RoomControllerTest.java index 8ce9d3d..98a9326 100644 --- a/src/test/java/web/chat/backend/controller/RoomControllerTest.java +++ b/src/test/java/web/chat/backend/controller/RoomControllerTest.java @@ -2,6 +2,7 @@ import static org.hamcrest.Matchers.*; import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.BDDMockito.any; import static org.mockito.BDDMockito.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.*; @@ -21,9 +22,10 @@ import org.springframework.web.bind.MethodArgumentNotValidException; import com.fasterxml.jackson.databind.ObjectMapper; - import lombok.RequiredArgsConstructor; +import web.chat.backend.controller.request.MessageRequest; import web.chat.backend.controller.request.RoomRequest; +import web.chat.backend.entity.Message; import web.chat.backend.entity.Room; import web.chat.backend.service.MessageService; import web.chat.backend.service.RoomService; @@ -118,4 +120,56 @@ void createRoom_titleLengthExceed_20() throws Exception { .andDo(print()); } + + @Test + void createMessage() throws Exception { + + // given + MessageRequest req = new MessageRequest(); + req.setContents("hi hello"); + + final String body = objectMapper.writeValueAsString(req); + + Message expected = new Message(); + expected.setId(1L); + expected.setContents(req.getContents()); + + given(roomService.getOrThrow(anyLong())).willReturn(new Room()); + given(messageService.createMessage(any(), any())).willReturn(expected); + + // when + ResultActions action = mockMvc.perform( + post("/api/rooms/1/messages") + .contentType(MediaType.APPLICATION_JSON) + .content(body)); + + // then + action.andDo(print()) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").value(expected.getId())) + .andExpect(jsonPath("$.contents").value(expected.getContents())); + } + + @DisplayName("Message 의 contents 빈값 불가능") + @Test + void createMessage_contentsLengthLessThan_1() throws Exception { + + // given + MessageRequest req = new MessageRequest(); + req.setContents(""); + + final String body = objectMapper.writeValueAsString(req); + + // when + ResultActions action = mockMvc.perform( + post("/api/rooms/1/messages") + .contentType(MediaType.APPLICATION_JSON) + .content(body)); + + // then + action.andDo(print()) + .andExpect(status().is4xxClientError()) + .andExpect(result -> assertTrue(result.getResolvedException() instanceof MethodArgumentNotValidException)); + + } } diff --git a/src/test/java/web/chat/backend/repository/MessageRepositoryTest.java b/src/test/java/web/chat/backend/repository/MessageRepositoryTest.java new file mode 100644 index 0000000..68c716c --- /dev/null +++ b/src/test/java/web/chat/backend/repository/MessageRepositoryTest.java @@ -0,0 +1,47 @@ +package web.chat.backend.repository; + +import static org.assertj.core.api.Assertions.*; + +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +import org.springframework.test.context.TestConstructor; + +import lombok.RequiredArgsConstructor; +import web.chat.backend.entity.Message; +import web.chat.backend.entity.Room; + +@TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL) +@RequiredArgsConstructor +@EnableJpaAuditing +@DataJpaTest +class MessageRepositoryTest { + + final TestEntityManager entityManager; + final MessageRepository messageRepository; + + @Test + void save() { + + // given + Room room = new Room(); + room.setTitle("room"); + + entityManager.persist(room); + + Message message = new Message(); + message.setContents("hi hello"); + message.setRoom(room); + + // when + Message savedMessage = messageRepository.save(message); + + // then + assertThat(savedMessage.getId()).isNotNull(); + assertThat(savedMessage.getContents()).isEqualTo(message.getContents()); + assertThat(savedMessage.getCreatedAt()).isNotNull(); + assertThat(savedMessage.getRoom()).isNotNull(); + assertThat(savedMessage.getRoom().getTitle()).isEqualTo(room.getTitle()); + } +} From 56cf4c828e4d079874e65badbe0a745b3e2d7602 Mon Sep 17 00:00:00 2001 From: "Seung Bin . Ko" Date: Sun, 30 Aug 2020 05:16:08 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=EC=A4=91=EB=B3=B5=EB=90=9C=20@Build?= =?UTF-8?q?er=20=EC=84=A4=EC=A0=95=20=EC=A0=9C=EA=B1=B0=20(#26)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/web/chat/backend/entity/Room.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/web/chat/backend/entity/Room.java b/src/main/java/web/chat/backend/entity/Room.java index 96b04bd..610f1c1 100644 --- a/src/main/java/web/chat/backend/entity/Room.java +++ b/src/main/java/web/chat/backend/entity/Room.java @@ -20,8 +20,6 @@ @Getter @Setter @Entity -@Builder - public class Room { @Id