From c951c18b17b087b82082edc165cb8618b69a413e Mon Sep 17 00:00:00 2001 From: GrimJak Date: Sat, 31 May 2025 16:18:48 +0300 Subject: [PATCH 1/2] =?UTF-8?q?COMMENTS-PRIVATE:=20=D0=9F=D0=BE=D0=BB?= =?UTF-8?q?=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=D0=BF=D0=B8=D1=81?= =?UTF-8?q?=D0=BA=D0=B0=20=D1=81=D0=B2=D0=BE=D0=B8=D1=85=20=D0=BA=D0=BE?= =?UTF-8?q?=D0=BC=D0=BC=D0=B5=D0=BD=D1=82=D0=B0=D1=80=D0=B8=D0=B5=D0=B2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../priv/PrivateCommentController.java | 17 ++++- .../main/repository/CommentRepository.java | 2 + .../main/service/CommentService.java | 2 + .../main/service/CommentServiceImpl.java | 14 +++++ .../priv/PrivateCommentControllerTest.java | 63 +++++++++++++++++-- .../main/service/CommentServiceImplTest.java | 62 ++++++++++++++++++ 6 files changed, 155 insertions(+), 5 deletions(-) diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentController.java b/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentController.java index c14849b..81e9856 100644 --- a/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentController.java +++ b/main-service/src/main/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentController.java @@ -2,6 +2,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.Positive; +import jakarta.validation.constraints.PositiveOrZero; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; @@ -13,6 +14,8 @@ import ru.practicum.explorewithme.main.dto.UpdateCommentDto; import ru.practicum.explorewithme.main.service.CommentService; +import java.util.List; + @RestController @RequestMapping("/users/{userId}/comments") @RequiredArgsConstructor @@ -36,7 +39,6 @@ public ResponseEntity createComment( } @PatchMapping("/{commentId}") - @ResponseStatus(HttpStatus.OK) public ResponseEntity updateComment( @PathVariable @Positive Long userId, @PathVariable @Positive Long commentId, @@ -47,4 +49,17 @@ public ResponseEntity updateComment( return ResponseEntity.status(HttpStatus.OK).body(commentService.updateUserComment(userId, commentId, updateCommentDto)); } + + @GetMapping + public ResponseEntity> getUserComments( + @PathVariable @Positive Long userId, + @RequestParam(defaultValue = "0") @PositiveOrZero int from, + @RequestParam(defaultValue = "10") @Positive int size) { + + List result = commentService.getUserComments(userId, from, size); + + log.info("Получение списка комментариев {} пользователя c id {}", result, userId); + + return ResponseEntity.status(HttpStatus.OK).body(result); + } } diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java b/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java index 4977c33..9d4f193 100644 --- a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java +++ b/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java @@ -12,4 +12,6 @@ public interface CommentRepository extends JpaRepository { @EntityGraph(attributePaths = {"author"}) Page findByEventIdAndIsDeletedFalse(Long eventId, Pageable pageable); + Page findByAuthorIdAndIsDeletedFalse(Long authorId, Pageable pageable); + } \ No newline at end of file diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentService.java b/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentService.java index 79bce6a..68e888a 100644 --- a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentService.java +++ b/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentService.java @@ -11,6 +11,8 @@ public interface CommentService { List getCommentsForEvent(Long eventId, PublicCommentParameters commentParameters); + List getUserComments(Long userId, int from, int size); + CommentDto addComment(Long userId, Long eventId, NewCommentDto newCommentDto); CommentDto updateUserComment(Long userId, Long commentId, UpdateCommentDto updateCommentDto); diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java b/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java index 6c6e63d..5a76c14 100644 --- a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java +++ b/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java @@ -52,6 +52,20 @@ public List getCommentsForEvent(Long eventId, PublicCommentParameter return commentMapper.toDtoList(result); } + @Override + @Transactional(readOnly = true) + public List getUserComments(Long userId, int from, int size) { + + User user = userRepository.findById(userId) + .orElseThrow(() -> new EntityNotFoundException("Пользователь с id " + userId + " не найден")); + + Pageable pageable = PageRequest.of(from / size, size); + + List result = commentRepository.findByAuthorIdAndIsDeletedFalse(userId, pageable).getContent(); + + return commentMapper.toDtoList(result); + } + @Override @Transactional public CommentDto addComment(Long userId, Long eventId, NewCommentDto newCommentDto) { diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentControllerTest.java b/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentControllerTest.java index d6d7cf5..88f0583 100644 --- a/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentControllerTest.java +++ b/main-service/src/test/java/ru/practicum/explorewithme/main/controller/priv/PrivateCommentControllerTest.java @@ -17,14 +17,13 @@ import ru.practicum.explorewithme.main.service.CommentService; import java.time.LocalDateTime; +import java.util.List; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.patch; -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; // <-- для post-запроса -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; @WebMvcTest(PrivateCommentController.class) @@ -213,4 +212,60 @@ void updateComment_shouldReturnBadRequest_whenBodyEmpty() throws Exception { .andExpect(jsonPath("$.errors[0]").value("text: Comment text cannot be blank.")); } } + + @Nested + @DisplayName("Набор тестов для метода getUserComments") + class GetUserComments { + + @Test + void getUserCommentsReturnsCommentsListWithStatusOk() throws Exception { + + List comments = List.of(commentDto); + + when(commentService.getUserComments(userId, 0, 10)).thenReturn(comments); + + mockMvc.perform(get("/users/{userId}/comments", userId) + .param("from", "0") + .param("size", "10") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().json(objectMapper.writeValueAsString(comments))); + + verify(commentService, times(1)).getUserComments(userId, 0, 10); + } + + @Test + void getUserCommentsReturnsEmptyListWhenNoComments() throws Exception { + + when(commentService.getUserComments(userId, 0, 10)).thenReturn(List.of()); + + mockMvc.perform(get("/users/{userId}/comments", userId) + .param("from", "0") + .param("size", "10") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().json("[]")); + } + + @Test + void getUserCommentsReturnsBadRequestWhenFromIsNegative() throws Exception { + + mockMvc.perform(get("/users/{userId}/comments", userId) + .param("from", "-1") + .param("size", "10") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + } + + @Test + void getUserCommentsReturnsBadRequestWhenSizeIsZero() throws Exception { + + mockMvc.perform(get("/users/{userId}/comments", userId) + .param("from", "0") + .param("size", "0") + .accept(MediaType.APPLICATION_JSON)) + .andExpect(status().isBadRequest()); + } + + } } diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java b/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java index 7ebbc11..390498f 100644 --- a/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java +++ b/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java @@ -5,6 +5,8 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; import ru.practicum.explorewithme.main.dto.CommentDto; import ru.practicum.explorewithme.main.dto.NewCommentDto; import ru.practicum.explorewithme.main.dto.UpdateCommentDto; @@ -20,8 +22,10 @@ import ru.practicum.explorewithme.main.repository.UserRepository; import java.time.LocalDateTime; +import java.util.List; import java.util.Optional; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -216,4 +220,62 @@ void updateUserComment_shouldThrowIfTooLate() { Assertions.assertTrue(ex.getMessage().contains("Время для редактирования истекло")); } } + + @Nested + @DisplayName("Набор тестов для метода getUserComments") + class GetUserComments { + + @Test + void getUserComments_shouldReturnEmptyList_whenNoComments() { + + when(userRepository.findById(userId)).thenReturn(java.util.Optional.of(user)); + when(commentRepository.findByAuthorIdAndIsDeletedFalse(eq(userId), any(Pageable.class))) + .thenReturn(new PageImpl<>(List.of())); + when(commentMapper.toDtoList(List.of())).thenReturn(List.of()); + + List result = commentService.getUserComments(userId, 0, 10); + + assertThat(result).isEmpty(); + + verify(userRepository).findById(userId); + verify(commentRepository).findByAuthorIdAndIsDeletedFalse(eq(userId), any(Pageable.class)); + verify(commentMapper).toDtoList(List.of()); + } + + @Test + void getUserComments_shouldReturnCommentsDtoList_whenCommentsExist() { + + List comments = List.of(comment); + CommentDto commentDto = new CommentDto(); // настрой по необходимости + List commentDtos = List.of(commentDto); + + when(userRepository.findById(userId)).thenReturn(java.util.Optional.of(user)); + when(commentRepository.findByAuthorIdAndIsDeletedFalse(eq(userId), any(Pageable.class))) + .thenReturn(new PageImpl<>(comments)); + when(commentMapper.toDtoList(comments)).thenReturn(commentDtos); + + List result = commentService.getUserComments(userId, 0, 10); + + assertThat(result).isEqualTo(commentDtos); + + verify(userRepository).findById(userId); + verify(commentRepository).findByAuthorIdAndIsDeletedFalse(eq(userId), any(Pageable.class)); + verify(commentMapper).toDtoList(comments); + } + + @Test + void getUserComments_shouldThrowException_whenUserNotFound() { + + when(userRepository.findById(userId)).thenReturn(java.util.Optional.empty()); + + EntityNotFoundException exception = assertThrows( + EntityNotFoundException.class, + () -> commentService.getUserComments(userId, 0, 10) + ); + + assertThat(exception.getMessage()).contains("Пользователь с id " + userId + " не найден"); + verify(userRepository).findById(userId); + verifyNoInteractions(commentRepository, commentMapper); + } + } } \ No newline at end of file From 8c18d53fa63eae41741dab6a1fa5396a74fc0423 Mon Sep 17 00:00:00 2001 From: GrimJak Date: Sat, 31 May 2025 19:12:11 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/repository/CommentRepository.java | 1 + .../main/service/CommentServiceImpl.java | 9 ++++++--- .../main/service/CommentServiceImplTest.java | 20 +++++++++---------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java b/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java index 9d4f193..87fc9c8 100644 --- a/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java +++ b/main-service/src/main/java/ru/practicum/explorewithme/main/repository/CommentRepository.java @@ -12,6 +12,7 @@ public interface CommentRepository extends JpaRepository { @EntityGraph(attributePaths = {"author"}) Page findByEventIdAndIsDeletedFalse(Long eventId, Pageable pageable); + @EntityGraph(attributePaths = {"author"}) Page findByAuthorIdAndIsDeletedFalse(Long authorId, Pageable pageable); } \ No newline at end of file diff --git a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java b/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java index 5a76c14..c3fa85c 100644 --- a/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java +++ b/main-service/src/main/java/ru/practicum/explorewithme/main/service/CommentServiceImpl.java @@ -3,6 +3,7 @@ import lombok.RequiredArgsConstructor; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import ru.practicum.explorewithme.main.dto.CommentDto; @@ -56,10 +57,12 @@ public List getCommentsForEvent(Long eventId, PublicCommentParameter @Transactional(readOnly = true) public List getUserComments(Long userId, int from, int size) { - User user = userRepository.findById(userId) - .orElseThrow(() -> new EntityNotFoundException("Пользователь с id " + userId + " не найден")); + if (!userRepository.existsById(userId)) { + throw new EntityNotFoundException("Пользователь с id " + userId + " не найден"); + } - Pageable pageable = PageRequest.of(from / size, size); + Sort sort = Sort.by(Sort.Direction.DESC, "createdOn"); + Pageable pageable = PageRequest.of(from / size, size, sort); List result = commentRepository.findByAuthorIdAndIsDeletedFalse(userId, pageable).getContent(); diff --git a/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java b/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java index 390498f..78394c9 100644 --- a/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java +++ b/main-service/src/test/java/ru/practicum/explorewithme/main/service/CommentServiceImplTest.java @@ -226,9 +226,9 @@ void updateUserComment_shouldThrowIfTooLate() { class GetUserComments { @Test - void getUserComments_shouldReturnEmptyList_whenNoComments() { + void getUserCommentsshouldReturnEmptyListwhenNoComments() { - when(userRepository.findById(userId)).thenReturn(java.util.Optional.of(user)); + when(userRepository.existsById(userId)).thenReturn(true); when(commentRepository.findByAuthorIdAndIsDeletedFalse(eq(userId), any(Pageable.class))) .thenReturn(new PageImpl<>(List.of())); when(commentMapper.toDtoList(List.of())).thenReturn(List.of()); @@ -237,19 +237,19 @@ void getUserComments_shouldReturnEmptyList_whenNoComments() { assertThat(result).isEmpty(); - verify(userRepository).findById(userId); + verify(userRepository).existsById(userId); verify(commentRepository).findByAuthorIdAndIsDeletedFalse(eq(userId), any(Pageable.class)); verify(commentMapper).toDtoList(List.of()); } @Test - void getUserComments_shouldReturnCommentsDtoList_whenCommentsExist() { + void getUserCommentsshouldReturnCommentsDtoListwhenCommentsExist() { List comments = List.of(comment); - CommentDto commentDto = new CommentDto(); // настрой по необходимости + CommentDto commentDto = new CommentDto(); List commentDtos = List.of(commentDto); - when(userRepository.findById(userId)).thenReturn(java.util.Optional.of(user)); + when(userRepository.existsById(userId)).thenReturn(true); when(commentRepository.findByAuthorIdAndIsDeletedFalse(eq(userId), any(Pageable.class))) .thenReturn(new PageImpl<>(comments)); when(commentMapper.toDtoList(comments)).thenReturn(commentDtos); @@ -258,15 +258,15 @@ void getUserComments_shouldReturnCommentsDtoList_whenCommentsExist() { assertThat(result).isEqualTo(commentDtos); - verify(userRepository).findById(userId); + verify(userRepository).existsById(userId); verify(commentRepository).findByAuthorIdAndIsDeletedFalse(eq(userId), any(Pageable.class)); verify(commentMapper).toDtoList(comments); } @Test - void getUserComments_shouldThrowException_whenUserNotFound() { + void getUserCommentsshouldThrowExceptionwhenUserNotFound() { - when(userRepository.findById(userId)).thenReturn(java.util.Optional.empty()); + when(userRepository.existsById(userId)).thenReturn(false); EntityNotFoundException exception = assertThrows( EntityNotFoundException.class, @@ -274,7 +274,7 @@ void getUserComments_shouldThrowException_whenUserNotFound() { ); assertThat(exception.getMessage()).contains("Пользователь с id " + userId + " не найден"); - verify(userRepository).findById(userId); + verify(userRepository).existsById(userId); verifyNoInteractions(commentRepository, commentMapper); } }