diff --git a/src/main/java/space/space_spring/controller/ChatRoomController.java b/src/main/java/space/space_spring/controller/ChatRoomController.java index aeccf610..50392f3d 100644 --- a/src/main/java/space/space_spring/controller/ChatRoomController.java +++ b/src/main/java/space/space_spring/controller/ChatRoomController.java @@ -16,7 +16,6 @@ import space.space_spring.response.BaseResponse; import space.space_spring.service.ChatRoomService; import space.space_spring.service.S3Uploader; -import space.space_spring.util.userSpace.UserSpaceUtils; import java.io.IOException; @@ -30,7 +29,6 @@ public class ChatRoomController { private final ChatRoomService chatRoomService; private final S3Uploader s3Uploader; - private final UserSpaceUtils userSpaceUtils; /** * 모든 채팅방 정보 조회 @@ -71,7 +69,7 @@ public BaseResponse updateLastReadTime( @JwtLoginAuth Long userId, @PathVariable Long spaceId, @PathVariable Long chatRoomId) { - return new BaseResponse<>(chatRoomService.updateLastReadTime(userId, spaceId, chatRoomId)); + return new BaseResponse<>(chatRoomService.updateLastReadTime(userId, chatRoomId)); } /** diff --git a/src/main/java/space/space_spring/dao/chat/ChatRoomDao.java b/src/main/java/space/space_spring/dao/chat/ChatRoomDao.java index 9c6ab523..e66f7798 100644 --- a/src/main/java/space/space_spring/dao/chat/ChatRoomDao.java +++ b/src/main/java/space/space_spring/dao/chat/ChatRoomDao.java @@ -4,11 +4,7 @@ import org.springframework.stereotype.Repository; import space.space_spring.dao.chat.custom.ChatRoomDaoCustom; import space.space_spring.entity.ChatRoom; -import space.space_spring.entity.Space; - -import java.util.List; @Repository public interface ChatRoomDao extends JpaRepository, ChatRoomDaoCustom { - List findBySpace(Space space); } diff --git a/src/main/java/space/space_spring/dto/chat/request/CreateChatRoomRequest.java b/src/main/java/space/space_spring/dto/chat/request/CreateChatRoomRequest.java index c492d0b9..e8143551 100644 --- a/src/main/java/space/space_spring/dto/chat/request/CreateChatRoomRequest.java +++ b/src/main/java/space/space_spring/dto/chat/request/CreateChatRoomRequest.java @@ -4,8 +4,8 @@ import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; +import lombok.Builder; import lombok.Getter; -import lombok.NoArgsConstructor; import lombok.Setter; import org.springframework.web.multipart.MultipartFile; @@ -13,7 +13,7 @@ @Getter @Setter -@NoArgsConstructor +@Builder public class CreateChatRoomRequest { @Size(min = 2, max = 15, message = "채팅방 이름은 2자 이상, 15자 이내의 문자열이어야 합니다.") diff --git a/src/main/java/space/space_spring/dto/chat/request/JoinChatRoomRequest.java b/src/main/java/space/space_spring/dto/chat/request/JoinChatRoomRequest.java index 63d41259..5b6e3d53 100644 --- a/src/main/java/space/space_spring/dto/chat/request/JoinChatRoomRequest.java +++ b/src/main/java/space/space_spring/dto/chat/request/JoinChatRoomRequest.java @@ -1,11 +1,17 @@ package space.space_spring.dto.chat.request; import jakarta.validation.constraints.NotEmpty; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; import java.util.List; @Getter +@Builder +@NoArgsConstructor /* controller단 테스트 위해 적용*/ +@AllArgsConstructor public class JoinChatRoomRequest { @NotEmpty(message = "1명 이상의 멤버를 초대해야 합니다.") diff --git a/src/main/java/space/space_spring/entity/ChatRoom.java b/src/main/java/space/space_spring/entity/ChatRoom.java index 0f3104da..754d42df 100644 --- a/src/main/java/space/space_spring/entity/ChatRoom.java +++ b/src/main/java/space/space_spring/entity/ChatRoom.java @@ -7,10 +7,6 @@ import lombok.Getter; import lombok.NoArgsConstructor; import org.hibernate.annotations.Comment; -import space.space_spring.dto.chat.request.CreateChatRoomRequest; - -import java.time.LocalDateTime; -import java.time.ZoneId; @Entity @Getter @@ -27,7 +23,7 @@ public class ChatRoom extends BaseEntity{ private Long id; @Comment("채팅방이 속한 스페이스 ID") - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "space_id") private Space space; @@ -40,10 +36,10 @@ public class ChatRoom extends BaseEntity{ @Column(name = "chat_room_img") private String img; - public static ChatRoom of(Space space, CreateChatRoomRequest createChatRoomRequest, String chatRoomImgUrl) { + public static ChatRoom of(Space space, String chatRoomName, String chatRoomImgUrl) { return ChatRoom.builder() .space(space) - .name(createChatRoomRequest.getName()) + .name(chatRoomName) .img(chatRoomImgUrl) .build(); } diff --git a/src/main/java/space/space_spring/entity/UserChatRoom.java b/src/main/java/space/space_spring/entity/UserChatRoom.java index 4b36bbfc..20ddb513 100644 --- a/src/main/java/space/space_spring/entity/UserChatRoom.java +++ b/src/main/java/space/space_spring/entity/UserChatRoom.java @@ -30,7 +30,7 @@ public class UserChatRoom extends BaseEntity{ private ChatRoom chatRoom; @Comment("사용자 ID") - @ManyToOne(fetch = FetchType.LAZY) + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumn(name = "user_id") private User user; diff --git a/src/main/java/space/space_spring/entity/document/ChatMessage.java b/src/main/java/space/space_spring/entity/document/ChatMessage.java index d55a8128..00643a0c 100644 --- a/src/main/java/space/space_spring/entity/document/ChatMessage.java +++ b/src/main/java/space/space_spring/entity/document/ChatMessage.java @@ -5,7 +5,6 @@ import org.springframework.data.annotation.Id; import org.springframework.data.annotation.TypeAlias; import org.springframework.data.mongodb.core.mapping.Document; -import space.space_spring.dto.chat.request.ChatMessageRequest; import space.space_spring.entity.enumStatus.ChatMessageType; import java.time.LocalDateTime; @@ -36,15 +35,15 @@ public class ChatMessage { private LocalDateTime createdAt; - public static ChatMessage of(ChatMessageRequest chatMessageRequest, Long chatRoomId, Long senderId, String senderName, String senderImg) { + public static ChatMessage of(HashMap content, Long chatRoomId, Long spaceId, Long senderId, String senderName, String senderImg, ChatMessageType messageType) { return ChatMessage.builder() - .content(chatMessageRequest.getContent()) + .content(content) .chatRoomId(chatRoomId) - .spaceId(chatMessageRequest.getSpaceId()) + .spaceId(spaceId) .senderId(senderId) .senderName(senderName) .senderImg(senderImg) - .messageType(chatMessageRequest.getMessageType()) + .messageType(messageType) .createdAt(LocalDateTime.now(ZoneId.of("Asia/Seoul"))) .build(); } diff --git a/src/main/java/space/space_spring/service/ChatRoomService.java b/src/main/java/space/space_spring/service/ChatRoomService.java index 3b3ccebc..24b17393 100644 --- a/src/main/java/space/space_spring/service/ChatRoomService.java +++ b/src/main/java/space/space_spring/service/ChatRoomService.java @@ -110,10 +110,14 @@ public CreateChatRoomResponse createChatRoom(Long userId, Long spaceId, CreateCh Space spaceBySpaceId = spaceUtils.findSpaceBySpaceId(spaceId); // TODO 3: chatRoom 생성 및 저장 - ChatRoom chatRoom = chatRoomDao.save(ChatRoom.of(spaceBySpaceId, createChatRoomRequest, chatRoomImgUrl)); + ChatRoom chatRoom = chatRoomDao.save(ChatRoom.of(spaceBySpaceId, createChatRoomRequest.getName(), chatRoomImgUrl)); // TODO 4: user_chatRoom 매핑 정보 저장 - UserChatRoom userChatRoom = userChatRoomDao.save(UserChatRoom.of(chatRoom, userByUserId, LocalDateTime.now())); + userChatRoomDao.save(UserChatRoom.of(chatRoom, userByUserId, LocalDateTime.now())); + for (Long id : createChatRoomRequest.getMemberList()) { + User user = userUtils.findUserByUserId(id); + userChatRoomDao.save(UserChatRoom.of(chatRoom, user, LocalDateTime.now())); + } // TODO 5: chatroom id 반환 return CreateChatRoomResponse.of(chatRoom.getId()); @@ -152,7 +156,7 @@ public ReadChatRoomMemberResponse readChatRoomMembers(Long spaceId, Long chatRoo } @Transactional - public ChatSuccessResponse updateLastReadTime(Long userId, Long spaceId, Long chatRoomId) { + public ChatSuccessResponse updateLastReadTime(Long userId, Long chatRoomId) { User userByUserId = userUtils.findUserByUserId(userId); ChatRoom chatRoomByChatRoomId = chatRoomDao.findById(chatRoomId) .orElseThrow(() -> new CustomException(CHATROOM_NOT_EXIST)); diff --git a/src/main/java/space/space_spring/service/ChattingService.java b/src/main/java/space/space_spring/service/ChattingService.java index 72b0e836..01f37b2f 100644 --- a/src/main/java/space/space_spring/service/ChattingService.java +++ b/src/main/java/space/space_spring/service/ChattingService.java @@ -58,11 +58,13 @@ public ChatMessageResponse sendChatMessage(Long senderId, ChatMessageRequest cha // TODO 4: DB에 메시지 저장 ChatMessage message = chattingDao.insert(ChatMessage.of( - chatMessageRequest, + chatMessageRequest.getContent(), chatRoomId, + chatMessageRequest.getSpaceId(), senderId, senderName, - senderProfileImg + senderProfileImg, + chatMessageRequest.getMessageType() )); return ChatMessageResponse.of(message); diff --git a/src/test/java/space/space_spring/controller/ChatRoomControllerTest.java b/src/test/java/space/space_spring/controller/ChatRoomControllerTest.java new file mode 100644 index 00000000..6d1c244b --- /dev/null +++ b/src/test/java/space/space_spring/controller/ChatRoomControllerTest.java @@ -0,0 +1,250 @@ +package space.space_spring.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +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.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; +import org.springframework.http.MediaType; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.web.servlet.MockMvc; +import space.space_spring.argumentResolver.jwtLogin.JwtLoginAuthHandlerArgumentResolver; +import space.space_spring.argumentResolver.userSpace.UserSpaceAuthHandlerArgumentResolver; +import space.space_spring.argumentResolver.userSpace.UserSpaceIdHandlerArgumentResolver; +import space.space_spring.config.SecurityConfig; +import space.space_spring.dto.chat.request.CreateChatRoomRequest; +import space.space_spring.dto.chat.request.JoinChatRoomRequest; +import space.space_spring.dto.chat.response.*; +import space.space_spring.dto.userSpace.UserInfoInSpace; +import space.space_spring.interceptor.UserSpaceValidationInterceptor; +import space.space_spring.interceptor.jwtLogin.JwtLoginAuthInterceptor; +import space.space_spring.service.ChatRoomService; +import space.space_spring.service.S3Uploader; + +import java.nio.charset.StandardCharsets; +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@WebMvcTest(ChatRoomController.class) +@MockBean(JpaMetamodelMappingContext.class) +@Import(SecurityConfig.class) +@AutoConfigureMockMvc(addFilters = false) // security config ignore +public class ChatRoomControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockBean + private ChatRoomService chatRoomService; + + @MockBean + private S3Uploader s3Uploader; + + @MockBean + private JwtLoginAuthHandlerArgumentResolver jwtLoginAuthHandlerArgumentResolver; + + @MockBean + private UserSpaceIdHandlerArgumentResolver userSpaceIdHandlerArgumentResolver; + + @MockBean + private UserSpaceAuthHandlerArgumentResolver userSpaceAuthHandlerArgumentResolver; + + @MockBean + private JwtLoginAuthInterceptor jwtLoginAuthInterceptor; + + @MockBean + private UserSpaceValidationInterceptor userSpaceValidationInterceptor; + + private static Long userId; + + private static Long spaceId; + + private static Long chatRoomId; + + private static Long userSpaceId; + + private static MockMultipartFile mockImgFile; + + private ChatSuccessResponse commonResponse; + + @BeforeEach + void 채팅방_테스트_설정() throws Exception { + userId = 0L; + spaceId = 1L; + userSpaceId = 2L; + chatRoomId = 3L; + + given(userSpaceValidationInterceptor.preHandle(any(), any(), any())) + .willReturn(true); + + given(jwtLoginAuthInterceptor.preHandle(any(), any(), any())) + .willReturn(true); + + given(jwtLoginAuthHandlerArgumentResolver.resolveArgument(any(), any(), any(), any())) + .willReturn(userId); + + given(userSpaceIdHandlerArgumentResolver.resolveArgument(any(), any(), any(), any())) + .willReturn(userSpaceId); + + given(userSpaceAuthHandlerArgumentResolver.resolveArgument(any(), any(), any(), any())) + .willReturn("manager"); + + mockImgFile = new MockMultipartFile("img", "test.png", "png", "test file".getBytes(StandardCharsets.UTF_8)); + + commonResponse = ChatSuccessResponse.builder().build(); + } + + @Test + @DisplayName("모든_채팅방_조회_테스트") + void 모든_채팅방_조회_테스트() throws Exception { + // given + ReadChatRoomResponse response = ReadChatRoomResponse.of(List.of(new ChatRoomResponse[]{})); + given(chatRoomService.readChatRooms(userId, spaceId)) + .willReturn(response); + + // when & then + mockMvc.perform(get("/space/{spaceId}/chat/chatroom", spaceId)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").exists()); + } + + @Test + @DisplayName("채팅방_생성_테스트") + void 채팅방_생성_테스트() throws Exception { + // given +// CreateChatRoomRequest request = new CreateChatRoomRequest(); + CreateChatRoomRequest request = CreateChatRoomRequest.builder() + .name("testChatRoom") + .img(mockImgFile) + .memberList(List.of(4L)) + .build(); +// request.setName("testChatRoom"); +// request.setImg(mockImgFile); +// request.setMemberList(List.of(4L)); + + CreateChatRoomResponse response = CreateChatRoomResponse.of(chatRoomId); + given(chatRoomService.createChatRoom(userId, spaceId, request, "asdf")) + .willReturn(response); + + // when & then + mockMvc.perform(multipart("/space/{spaceId}/chat/chatroom", spaceId) + .file(mockImgFile) + .param("name", request.getName()) + .param("memberList", request.getMemberList().stream() + .map(String::valueOf) + .toArray(String[]::new)) + .param("userSpaceAuth", "manager") + .contentType(MediaType.MULTIPART_FORM_DATA)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").exists()); + } + + @Test + @DisplayName("특정_채팅방의_모든_유저_정보_조회_테스트") + void 특정_채팅방의_모든_유저_정보_조회_테스트() throws Exception { + // given + ReadChatRoomMemberResponse response = ReadChatRoomMemberResponse.of(List.of(new UserInfoInSpace[]{})); + given(chatRoomService.readChatRoomMembers(userId, spaceId)) + .willReturn(response); + + // when & then + mockMvc.perform(get("/space/{spaceId}/chat/{chatRoomId}/member", spaceId, chatRoomId)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").exists()); + } + + @Test + @DisplayName("특정_채팅방에_유저_초대_테스트") + void 특정_채팅방에_유저_초대_테스트() throws Exception { + // given + JoinChatRoomRequest request = JoinChatRoomRequest.builder().memberList(List.of(1L)).build(); + String content = objectMapper.writeValueAsString(request); + + given(chatRoomService.joinChatRoom(chatRoomId, request)) + .willReturn(commonResponse); + + // when & then + mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/member", spaceId, chatRoomId) + .param("userSpaceAuth", "manager") + .contentType(MediaType.APPLICATION_JSON) + .content(content)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").exists()); + } + + @Test + @DisplayName("특정_유저가_채팅방에서_떠난_시간_저장_테스트") + void 특정_유저가_채팅방에서_떠난_시간_저장_테스트() throws Exception { + // given + given(chatRoomService.updateLastReadTime(userId, chatRoomId)) + .willReturn(commonResponse); + + // when & then + mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/leave", spaceId, chatRoomId)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").exists()); + } + + @Test + @DisplayName("특정_채팅방의_이름_수정_테스트") + void 특정_채팅방의_이름_수정_테스트() throws Exception { + // given + given(chatRoomService.modifyChatRoomName(chatRoomId, "newChatRoom")) + .willReturn(commonResponse); + + // when & then + mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/setting", spaceId, chatRoomId) + .param("name", "newChatRoom") + .param("userSpaceAuth", "manager")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").exists()); + } + + @Test + @DisplayName("특정_채팅방에서_나가기_테스트") + void 특정_채팅방에서_나가기_테스트() throws Exception { + // given + given(chatRoomService.exitChatRoom(userId, chatRoomId)) + .willReturn(commonResponse); + + // when & then + mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/exit", spaceId, chatRoomId)) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").exists()); + } + + @Test + @DisplayName("특정_채팅방_삭제_테스트") + void 특정_채팅방_삭제_테스트() throws Exception { + // given + given(chatRoomService.deleteChatRoom(chatRoomId)) + .willReturn(commonResponse); + + // when & then + mockMvc.perform(post("/space/{spaceId}/chat/{chatRoomId}/delete", spaceId, chatRoomId) + .param("userSpaceAuth", "manager")) + .andDo(print()) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.message").exists()); + } +} diff --git a/src/test/java/space/space_spring/repository/ChatRoomDaoTest.java b/src/test/java/space/space_spring/repository/ChatRoomDaoTest.java new file mode 100644 index 00000000..4748b831 --- /dev/null +++ b/src/test/java/space/space_spring/repository/ChatRoomDaoTest.java @@ -0,0 +1,100 @@ +package space.space_spring.repository; + +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import space.space_spring.config.QueryDslConfig; +import space.space_spring.dao.chat.ChatRoomDao; +import space.space_spring.dao.chat.UserChatRoomDao; +import space.space_spring.entity.ChatRoom; +import space.space_spring.entity.Space; +import space.space_spring.entity.User; +import space.space_spring.entity.UserChatRoom; +import space.space_spring.entity.enumStatus.UserSignupType; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.*; + +@DataJpaTest +@Import({QueryDslConfig.class, QueryDslConfig.class}) +public class ChatRoomDaoTest { + + @Autowired + private ChatRoomDao chatRoomDao; + + @Autowired + private UserChatRoomDao userChatRoomDao; + + private Space testSpace; + + private ChatRoom testChatRoom1; + + private ChatRoom testChatRoom2; + + private User testUser; + + @BeforeEach + void 테스트_셋업() { + testUser = new User(); + + testUser.saveUser("testUser@test.com", "Asdf1234!", "testUser", UserSignupType.LOCAL); + + testSpace = new Space(); + + // testSpace에 속한 chatRoom 엔티티 생성 + testChatRoom1 = ChatRoom.of(testSpace, "testChatRoom1", ""); + testChatRoom2 = ChatRoom.of(testSpace, "testChatRoom2", ""); + } + + @Test + @DisplayName("채팅방_저장_테스트") + void 채팅방_저장_테스트() { + // given + + // when + ChatRoom savedTestChatRoom1 = chatRoomDao.save(testChatRoom1); + ChatRoom savedTestChatRoom2 = chatRoomDao.save(testChatRoom2); + + // then + assertThat(savedTestChatRoom1.getId()).isEqualTo(testChatRoom1.getId()); + assertThat(savedTestChatRoom2.getId()).isEqualTo(testChatRoom2.getId()); + } + + @Test + @DisplayName("id로_채팅방_조회_테스트") + void id로_채팅방_조회_테스트() { + // given + ChatRoom savedTestChatRoom1 = chatRoomDao.save(testChatRoom1); + ChatRoom savedTestChatRoom2 = chatRoomDao.save(testChatRoom2); + + // when + Optional chatRoom1byId = chatRoomDao.findById(savedTestChatRoom1.getId()); + Optional chatRoom2byId = chatRoomDao.findById(savedTestChatRoom2.getId()); + + // then + chatRoom1byId.ifPresent(chatRoom -> assertThat(chatRoom.getId()).isEqualTo(savedTestChatRoom1.getId())); + chatRoom2byId.ifPresent(chatRoom -> assertThat(chatRoom.getId()).isEqualTo(savedTestChatRoom2.getId())); + } + + @Test + @DisplayName("유저와_스페이스로_채팅방_조회_테스트") + void 유저와_스페이스로_채팅방_조회_테스트() { + // given + ChatRoom savedTestChatRoom1 = chatRoomDao.save(testChatRoom1); + ChatRoom savedTestChatRoom2 = chatRoomDao.save(testChatRoom2); + UserChatRoom userChatRoom1 = UserChatRoom.of(savedTestChatRoom1, testUser, LocalDateTime.now()); + UserChatRoom userChatRoom2 = UserChatRoom.of(savedTestChatRoom2, testUser, LocalDateTime.now()); + userChatRoomDao.save(userChatRoom1); + userChatRoomDao.save(userChatRoom2); + + // when + List chatRoomListByUser = chatRoomDao.findByUserAndSpace(testUser, testSpace); + + // then + assertThat(chatRoomListByUser.size()).isEqualTo(2); + } +} diff --git a/src/test/java/space/space_spring/repository/UserChatRoomDaoTest.java b/src/test/java/space/space_spring/repository/UserChatRoomDaoTest.java new file mode 100644 index 00000000..3d3ddad1 --- /dev/null +++ b/src/test/java/space/space_spring/repository/UserChatRoomDaoTest.java @@ -0,0 +1,107 @@ +package space.space_spring.repository; + +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; +import org.springframework.context.annotation.Import; +import space.space_spring.config.QueryDslConfig; +import space.space_spring.dao.chat.ChatRoomDao; +import space.space_spring.dao.chat.UserChatRoomDao; +import space.space_spring.entity.ChatRoom; +import space.space_spring.entity.Space; +import space.space_spring.entity.User; +import space.space_spring.entity.UserChatRoom; +import space.space_spring.entity.enumStatus.UserSignupType; + +import java.time.LocalDateTime; +import java.util.List; + +import static org.assertj.core.api.Assertions.*; + +@DataJpaTest +@Import({QueryDslConfig.class, QueryDslConfig.class}) +@TestMethodOrder(value = MethodOrderer.OrderAnnotation.class) +public class UserChatRoomDaoTest { + + @Autowired + private UserChatRoomDao userChatRoomDao; + + @Autowired + private ChatRoomDao chatRoomDao; + + private User testUser1; + + private User testUser2; + + private UserChatRoom testUserChatRoom1; + + private UserChatRoom testUserChatRoom2; + + private ChatRoom testChatRoom; + + @BeforeEach + void 테스트_셋업() { + testUser1 = new User(); + testUser2 = new User(); + + testUser1.saveUser("testUser1@test.com", "Asdf1234!", "testUser1", UserSignupType.LOCAL); + testUser2.saveUser("testUser2@test.com", "Asdf1234!", "testUser2", UserSignupType.LOCAL); + + Space testSpace = new Space(); + + // testSpace에 속한 채팅방 생성 및 저장 + testChatRoom = ChatRoom.of(testSpace, "testChatRoom", ""); + chatRoomDao.save(testChatRoom); + + // testChatRoom에 대한 testUserChatRoom 엔티티 생성 + testUserChatRoom1 = UserChatRoom.of(testChatRoom, testUser1, LocalDateTime.now()); + testUserChatRoom2 = UserChatRoom.of(testChatRoom, testUser2, LocalDateTime.now()); + } + + @Test + @DisplayName("유저채팅방_저장_테스트") + void 유저채팅방_저장_테스트() { + // given + + // when + UserChatRoom savedTestUserChatRoom1 = userChatRoomDao.save(testUserChatRoom1); + UserChatRoom savedTestUserChatRoom2 = userChatRoomDao.save(testUserChatRoom2); + + // then + assertThat(savedTestUserChatRoom1.getId()).isEqualTo(testUserChatRoom1.getId()); + assertThat(savedTestUserChatRoom2.getId()).isEqualTo(testUserChatRoom2.getId()); + + assertThat(savedTestUserChatRoom1.getUser().getUserId()).isEqualTo(testUser1.getUserId()); + assertThat(savedTestUserChatRoom2.getUser().getUserId()).isEqualTo(testUser2.getUserId()); + } + + @Test + @DisplayName("채팅방으로_유저채팅방_조회_테스트") + void 채팅방으로_유저채팅방_저장_테스트() { + // given + userChatRoomDao.save(testUserChatRoom1); + userChatRoomDao.save(testUserChatRoom2); + + // when + List userChatRoomList = userChatRoomDao.findByChatRoom(testChatRoom); + + // then + assertThat(userChatRoomList.size()).isEqualTo(2); + } + + @Test + @DisplayName("유저와_채팅방으로_유저채팅방_저장_테스트") + void 유저와_채팅방으로_유저채팅방_저장_테스트() { + // given + userChatRoomDao.save(testUserChatRoom1); + userChatRoomDao.save(testUserChatRoom2); + + // when + UserChatRoom userChatRoom1 = userChatRoomDao.findByUserAndChatRoom(testUser1, testChatRoom); + UserChatRoom userChatRoom2 = userChatRoomDao.findByUserAndChatRoom(testUser2, testChatRoom); + + // then + assertThat(userChatRoom1.getId()).isEqualTo(testUserChatRoom1.getId()); + assertThat(userChatRoom2.getId()).isEqualTo(testUserChatRoom2.getId()); + } +} diff --git a/src/test/java/space/space_spring/service/ChatRoomServiceTest.java b/src/test/java/space/space_spring/service/ChatRoomServiceTest.java new file mode 100644 index 00000000..97facaf5 --- /dev/null +++ b/src/test/java/space/space_spring/service/ChatRoomServiceTest.java @@ -0,0 +1,340 @@ +package space.space_spring.service; + +import org.junit.jupiter.api.*; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.mock.web.MockMultipartFile; +import org.springframework.test.util.ReflectionTestUtils; +import space.space_spring.dao.UserSpaceDao; +import space.space_spring.dao.chat.ChatRoomDao; +import space.space_spring.dao.chat.ChattingDao; +import space.space_spring.dao.chat.UserChatRoomDao; +import space.space_spring.dto.chat.request.CreateChatRoomRequest; +import space.space_spring.dto.chat.request.JoinChatRoomRequest; +import space.space_spring.dto.chat.response.ChatSuccessResponse; +import space.space_spring.dto.chat.response.CreateChatRoomResponse; +import space.space_spring.dto.chat.response.ReadChatRoomMemberResponse; +import space.space_spring.dto.chat.response.ReadChatRoomResponse; +import space.space_spring.entity.*; +import space.space_spring.entity.enumStatus.UserSignupType; +import space.space_spring.entity.enumStatus.UserSpaceAuth; +import space.space_spring.util.space.SpaceUtils; +import space.space_spring.util.user.UserUtils; + +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.List; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.*; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class ChatRoomServiceTest { + + @InjectMocks + private ChatRoomService chatRoomService; + + @Mock + private ChatRoomDao chatRoomDao; + + @Mock + private UserUtils userUtils; + + @Mock + private SpaceUtils spaceUtils; + + @Mock + private UserSpaceDao userSpaceDao; + + @Mock + private ChattingDao chattingDao; + + @Mock + private UserChatRoomDao userChatRoomDao; + + private User user1; + + private User user2; + + private User user3; + + private Space testSpace; + + private UserSpace testUserSpace1; + + private UserSpace testUserSpace2; + + private UserSpace testUserSpace3; + + private ChatRoom chatRoom1; + + private ChatRoom chatRoom2; + + private UserChatRoom userChatRoom1; + + private UserChatRoom userChatRoom2; + + private UserChatRoom userChatRoom1ByUser2; + + private UserChatRoom userChatRoom1ByUser3; + + private CreateChatRoomRequest createChatRoomRequest1; + + private CreateChatRoomRequest createChatRoomRequest2; + + private JoinChatRoomRequest joinChatRoomRequest; + + private LocalDateTime mockTime; + + @BeforeEach + void 채팅방_테스트_설정() { + /** + * <관리자인 user1은 chatRoom1, chatRoom2 생성> + * + */ + user1 = createUser("user1@test.com", 0L); + user2 = createUser("user2@test.com", 1L); + user3 = createUser("user3@test.com", 2L); + + testSpace = new Space(); + testSpace.saveSpace("testSpace", ""); + ReflectionTestUtils.setField(testSpace, "spaceId", 0L); + lenient().when(spaceUtils.findSpaceBySpaceId(0L)).thenReturn(testSpace); + + testUserSpace1 = new UserSpace(); + testUserSpace2 = new UserSpace(); + testUserSpace3 = new UserSpace(); + testUserSpace1.createUserSpace(this.user1, testSpace, UserSpaceAuth.MANAGER); + testUserSpace2.createUserSpace(this.user2, testSpace, UserSpaceAuth.NORMAL); + testUserSpace3.createUserSpace(user3, testSpace, UserSpaceAuth.NORMAL); + + mockTime = LocalDateTime.now(); + + lenient().when(chatRoomDao.save(any(ChatRoom.class))).thenAnswer(invocationOnMock -> { + ChatRoom savedChatRoom = invocationOnMock.getArgument(0); + if ("chatRoom1".equals(savedChatRoom.getName())) { + chatRoom1 = createChatRoom("chatRoom1", 0L); + return chatRoom1; + } else if ("chatRoom2".equals(savedChatRoom.getName())) { + chatRoom2 = createChatRoom("chatRoom2", 1L); + return chatRoom2; + } + return null; + }); + + // chatRoom1, chatRoom2 생성 시 사용할 request + MockMultipartFile mockImgFile = new MockMultipartFile("mockImgFile", "test.png", "png", "test file".getBytes(StandardCharsets.UTF_8) ); + + createChatRoomRequest1 = CreateChatRoomRequest.builder() + .name("chatRoom1") + .img(mockImgFile) + .memberList(List.of(1L)) + .build(); + + createChatRoomRequest2 = CreateChatRoomRequest.builder() + .name("chatRoom2") + .img(mockImgFile) + .memberList(List.of()) + .build(); + + // user3 초대 시 사용할 request + joinChatRoomRequest = JoinChatRoomRequest.builder().memberList(List.of(2L)).build(); + + lenient().when(userChatRoomDao.save(any(UserChatRoom.class))).thenAnswer(invocationOnMock -> { + UserChatRoom savedChatRoom = invocationOnMock.getArgument(0); + if ("chatRoom1".equals(savedChatRoom.getChatRoom().getName())) { + if ("user1".equals(savedChatRoom.getUser().getUserName())) { + userChatRoom1 = createUserChatRoom(0L, chatRoom1, user1); + return userChatRoom1; + } else if ("user2".equals(savedChatRoom.getUser().getUserName())) { + userChatRoom1ByUser2 = createUserChatRoom(1L, chatRoom1, user2); + return userChatRoom1ByUser2; + } else { + userChatRoom1ByUser3 = createUserChatRoom(2L, chatRoom1, user3); + return userChatRoom1ByUser3; + } + } else if ("chatRoom2".equals(savedChatRoom.getChatRoom().getName())) { + userChatRoom2 = createUserChatRoom(3L, chatRoom2, user1); + return userChatRoom2; + } + return null; + }); + } + + @Test + @DisplayName("특정_스페이스_내의_채팅방_생성_테스트") + void 특정_스페이스_내의_채팅방_생성_테스트() { + // given + + // when + CreateChatRoomResponse createdChatRoom1 = chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest1, ""); + CreateChatRoomResponse createdChatRoom2 = chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest2, ""); + + // then + assertThat(createdChatRoom1.getChatRoomId()).isEqualTo(0L); + assertThat(createdChatRoom2.getChatRoomId()).isEqualTo(1L); + } + + @Test + @DisplayName("특정_스페이스_내의_전체_채팅방_조회_테스트") + void 특정_스페이스_내의_전체_채팅방_조회_테스트() { + // given + chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest1, ""); + chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest2, ""); + + when(chattingDao.findTopByChatRoomIdOrderByCreatedAtDesc(chatRoom1.getId())).thenReturn(null); // 마지막 메시지가 없다고 가정 + when(chattingDao.countByChatRoomIdAndCreatedAtBetween(chatRoom1.getId(), convertToKoreaTime(mockTime), convertToKoreaTime(mockTime))).thenReturn(0); + when(chatRoomDao.findByUserAndSpace(user1, testSpace)).thenReturn(List.of(chatRoom1, chatRoom2)); + when(userChatRoomDao.findByUserAndChatRoom(user1, chatRoom1)).thenReturn(userChatRoom1); + + when(chattingDao.findTopByChatRoomIdOrderByCreatedAtDesc(chatRoom2.getId())).thenReturn(null); // 마지막 메시지가 없다고 가정 + when(chattingDao.countByChatRoomIdAndCreatedAtBetween(chatRoom2.getId(), convertToKoreaTime(mockTime), convertToKoreaTime(mockTime))).thenReturn(0); + when(userChatRoomDao.findByUserAndChatRoom(user1, chatRoom2)).thenReturn(userChatRoom2); + + // when + ReadChatRoomResponse readChatRoomResponse = chatRoomService.readChatRooms(user1.getUserId(), testSpace.getSpaceId()); + + // then + assertThat(readChatRoomResponse.getChatRoomList().size()).isEqualTo(2); + assertThat(readChatRoomResponse.getChatRoomList().get(0).getName()).isEqualTo("chatRoom1"); + assertThat(readChatRoomResponse.getChatRoomList().get(1).getName()).isEqualTo("chatRoom2"); + } + + @Test + @DisplayName("특정_채팅방의_전체_멤버_조회_테스트") + void 특정_채팅방의_전체_멤버_조회_테스트() { + // given + chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest1, ""); + chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest2, ""); + + when(chatRoomDao.findById(chatRoom1.getId())).thenReturn(Optional.ofNullable(chatRoom1)); + when(userChatRoomDao.findByChatRoom(chatRoom1)).thenReturn(List.of(userChatRoom1, userChatRoom1ByUser2)); + when(userSpaceDao.findUserSpaceByUserAndSpace(user1, testSpace)).thenReturn(Optional.ofNullable(testUserSpace1)); + + when(chatRoomDao.findById(chatRoom2.getId())).thenReturn(Optional.ofNullable(chatRoom2)); + when(userChatRoomDao.findByChatRoom(chatRoom2)).thenReturn(List.of(userChatRoom2)); + when(userSpaceDao.findUserSpaceByUserAndSpace(user2, testSpace)).thenReturn(Optional.ofNullable(testUserSpace2)); + + // when + ReadChatRoomMemberResponse readChatRoomMemberResponse1 = chatRoomService.readChatRoomMembers(testSpace.getSpaceId(), chatRoom1.getId()); + ReadChatRoomMemberResponse readChatRoomMemberResponse2 = chatRoomService.readChatRoomMembers(testSpace.getSpaceId(), chatRoom2.getId()); + + // then + assertThat(readChatRoomMemberResponse1.getUserList().size()).isEqualTo(2); + assertThat(readChatRoomMemberResponse1.getUserList().get(0).getUserId()).isEqualTo(0L); + assertThat(readChatRoomMemberResponse1.getUserList().get(1).getUserId()).isEqualTo(1L); + assertThat(readChatRoomMemberResponse2.getUserList().size()).isEqualTo(1); + assertThat(readChatRoomMemberResponse2.getUserList().get(0).getUserId()).isEqualTo(0L); + } + + @Test + @DisplayName("특정_채팅방으로의_멤버_초대_테스트") + void 특정_채팅방으로의_멤버_초대_테스트() { + // given + chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest1, ""); + when(chatRoomDao.findById(chatRoom1.getId())).thenReturn(Optional.ofNullable(chatRoom1)); + when(userChatRoomDao.findByChatRoom(chatRoom1)).thenReturn(List.of(userChatRoom1, userChatRoom1ByUser2)); + + // when + ChatSuccessResponse chatSuccessResponse = chatRoomService.joinChatRoom(chatRoom1.getId(), joinChatRoomRequest); + + // then + assertThat(chatSuccessResponse.isSuccess()).isEqualTo(true); + } + + @Test + @DisplayName("특정_채팅방에서_특정_유저가_마지막으로_읽은_시간_수정_테스트") + void 특정_채팅방에서_특정_유저가_마지막으로_읽은_시간_수정_테스트() { + // given + chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest1, ""); + when(chatRoomDao.findById(chatRoom1.getId())).thenReturn(Optional.ofNullable(chatRoom1)); + when(userChatRoomDao.findByUserAndChatRoom(user1, chatRoom1)).thenReturn(userChatRoom1); + + // when + ChatSuccessResponse chatSuccessResponse = chatRoomService.updateLastReadTime(user1.getUserId(), chatRoom1.getId()); + + // then + assertThat(chatSuccessResponse.isSuccess()).isEqualTo(true); + } + + @Test + @DisplayName("특정_채팅방_이름_수정_테스트") + void 특정_채팅방_이름_수정_테스트() { + // given + chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest1, ""); + when(chatRoomDao.findById(chatRoom1.getId())).thenReturn(Optional.ofNullable(chatRoom1)); + + // when + ChatSuccessResponse chatSuccessResponse = chatRoomService.modifyChatRoomName(chatRoom1.getId(), "newChatRoom1"); + + // then + assertThat(chatSuccessResponse.isSuccess()).isEqualTo(true); + } + + @Test + @DisplayName("특정_채팅방_나가기_테스트") + void 특정_채팅방_나가기_테스트() { + // given + chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest1, ""); + when(chatRoomDao.findById(chatRoom1.getId())).thenReturn(Optional.ofNullable(chatRoom1)); + when(userChatRoomDao.findByUserAndChatRoom(user2, chatRoom1)).thenReturn(userChatRoom1ByUser2); + + // when + ChatSuccessResponse chatSuccessResponse = chatRoomService.exitChatRoom(user2.getUserId(), chatRoom1.getId()); + + // then + assertThat(chatSuccessResponse.isSuccess()).isEqualTo(true); + } + + @Test + @DisplayName("특정_채팅방_삭제_테스트") + void 특정_채팅방_삭제_테스트() { + // given + chatRoomService.createChatRoom(user1.getUserId(), testSpace.getSpaceId(), createChatRoomRequest1, ""); + when(chatRoomDao.findById(chatRoom1.getId())).thenReturn(Optional.ofNullable(chatRoom1)); + + // when + ChatSuccessResponse chatSuccessResponse = chatRoomService.deleteChatRoom(chatRoom1.getId()); + + // then + assertThat(chatSuccessResponse.isSuccess()).isEqualTo(true); + } + + private User createUser(String email, Long userId) { + User user = new User(); + user.saveUser(email, "Asdf1234!", email.split("@")[0], UserSignupType.LOCAL); + ReflectionTestUtils.setField(user, "userId", userId); + lenient().when(userUtils.findUserByUserId(userId)).thenReturn(user); + return user; + } + + private ChatRoom createChatRoom(String name, Long id) { + ChatRoom chatRoom = new ChatRoom(); + ReflectionTestUtils.setField(chatRoom, "id", id); + ReflectionTestUtils.setField(chatRoom, "status", "ACTIVE"); + ReflectionTestUtils.setField(chatRoom, "createdAt", mockTime); + ReflectionTestUtils.setField(chatRoom, "name", name); + return chatRoom; + } + + private UserChatRoom createUserChatRoom(Long id, ChatRoom chatRoom, User user) { + UserChatRoom userChatRoom = new UserChatRoom(); + ReflectionTestUtils.setField(userChatRoom, "id", id); + ReflectionTestUtils.setField(userChatRoom, "status", "ACTIVE"); + ReflectionTestUtils.setField(userChatRoom, "createdAt", mockTime); + ReflectionTestUtils.setField(userChatRoom, "chatRoom", chatRoom); + ReflectionTestUtils.setField(userChatRoom, "user", user); + ReflectionTestUtils.setField(userChatRoom, "lastReadTime", mockTime); + return userChatRoom; + } + + private LocalDateTime convertToKoreaTime(LocalDateTime time) { + return time.atZone(ZoneId.of("UTC")) + .withZoneSameInstant(ZoneId.of("Asia/Seoul")) + .toLocalDateTime(); + } +}