diff --git a/README.md b/README.md
index 745d97a..86abe0d 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,3 @@
# REST API using Spring Boot
- ## task 1
+ ## task 2
diff --git a/pom.xml b/pom.xml
index 4270842..8575695 100644
--- a/pom.xml
+++ b/pom.xml
@@ -49,6 +49,11 @@
spring-boot-starter-test
test
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-jsr310
+
diff --git a/src/main/java/task/repository/TaskRepository.java b/src/main/java/task/repository/TaskRepository.java
index 086dc26..26c18ac 100644
--- a/src/main/java/task/repository/TaskRepository.java
+++ b/src/main/java/task/repository/TaskRepository.java
@@ -11,6 +11,7 @@ public interface TaskRepository {
public List findByUserIdAndIsDeleteFalse(Long userId);
public List findByUserIdAndIsCompleteFalseAndIsDeleteFalse(Long userId) ;
public Task save(Task task) ;
+ public Optional findByIdAndIsDeleteFalse(Long taskId);
public void markAsDeleted(Long taskId);
}
diff --git a/src/main/java/task/repository/impl/TaskRepositoryImpl.java b/src/main/java/task/repository/impl/TaskRepositoryImpl.java
index 406e53a..2a08f1c 100644
--- a/src/main/java/task/repository/impl/TaskRepositoryImpl.java
+++ b/src/main/java/task/repository/impl/TaskRepositoryImpl.java
@@ -47,6 +47,11 @@ public Task save(Task task) {
return task;
}
@Override
+ public Optional findByIdAndIsDeleteFalse(Long taskId) {
+ Task task = tasks.get(taskId);
+ return (task != null && !task.getIsDelete()) ? Optional.of(task) : Optional.empty();
+ }
+ @Override
public void markAsDeleted(Long taskId) {
Optional.ofNullable(tasks.get(taskId))
.ifPresent(task -> task.setIsDelete(true));
diff --git a/src/test/java/task/controller/NotificationControllerTest.java b/src/test/java/task/controller/NotificationControllerTest.java
new file mode 100644
index 0000000..a004079
--- /dev/null
+++ b/src/test/java/task/controller/NotificationControllerTest.java
@@ -0,0 +1,96 @@
+package task.controller;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import task.model.Notification;
+import task.service.NotificationService;
+
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+class NotificationControllerTest {
+
+ private MockMvc mockMvc;
+ private ObjectMapper objectMapper;
+
+ @Mock
+ private NotificationService notificationService;
+
+ @InjectMocks
+ private NotificationController notificationController;
+
+ private Notification notification;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+ mockMvc = MockMvcBuilders.standaloneSetup(notificationController).build();
+ objectMapper = new ObjectMapper();
+ objectMapper.registerModule(new JavaTimeModule());
+
+ notification = Notification.builder()
+ .notificationId(1L)
+ .text("New task available")
+ .userId(1L)
+ .taskId(2L)
+ .isRead(false)
+ .build();
+ }
+
+ @Test
+ void getAllNotifications_WhenExist_ReturnsOkAndList() throws Exception {
+ when(notificationService.getAllNotifications()).thenReturn(List.of(notification));
+
+ mockMvc.perform(get("/api/notifications"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].text").value("New task available"));
+
+ verify(notificationService).getAllNotifications();
+ }
+
+ @Test
+ void getUserNotifications_ValidUserId_ReturnsOkAndList() throws Exception {
+ when(notificationService.getUserNotifications(1L)).thenReturn(List.of(notification));
+
+ mockMvc.perform(get("/api/notifications/user/1"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].userId").value(1));
+
+ verify(notificationService).getUserNotifications(1L);
+ }
+
+ @Test
+ void getUserNotificationsUnread_UnreadExist_ReturnsOkAndUnreadList() throws Exception {
+ when(notificationService.getUserNotificationsUnread(1L)).thenReturn(List.of(notification));
+
+ mockMvc.perform(get("/api/notifications/user/1/unread"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].isRead").value(false));
+
+ verify(notificationService).getUserNotificationsUnread(1L);
+ }
+
+ @Test
+ void createNotification_ValidData_ReturnsCreated() throws Exception {
+ when(notificationService.createNotification(any(Notification.class))).thenReturn(notification);
+
+ mockMvc.perform(post("/api/notifications")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(notification)))
+ .andExpect(status().isCreated())
+ .andExpect(jsonPath("$.text").value("New task available"));
+
+ verify(notificationService).createNotification(any(Notification.class));
+ }
+}
diff --git a/src/test/java/task/controller/TaskControllerTest.java b/src/test/java/task/controller/TaskControllerTest.java
new file mode 100644
index 0000000..75e27f8
--- /dev/null
+++ b/src/test/java/task/controller/TaskControllerTest.java
@@ -0,0 +1,96 @@
+package task.controller;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import task.model.Task;
+import task.service.TaskService;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static org.mockito.Mockito.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+
+class TaskControllerTest {
+
+ private MockMvc mockMvc;
+ private ObjectMapper objectMapper;
+
+ @Mock
+ private TaskService taskService;
+
+ @InjectMocks
+ private TaskController taskController;
+
+ private Task task;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+ mockMvc = MockMvcBuilders.standaloneSetup(taskController).build();
+ objectMapper = new ObjectMapper();
+
+ objectMapper.registerModule(new JavaTimeModule());
+
+ task = Task.builder()
+ .taskId(1L)
+ .taskText("Sample Task")
+ .userId(1L)
+ .createDate(LocalDateTime.now())
+ .build();
+ }
+
+ @Test
+ void getAllTasks_WhenTasksExist_ReturnsOkAndList() throws Exception {
+ when(taskService.getAllTasks()).thenReturn(List.of(task));
+
+ mockMvc.perform(get("/api/tasks"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].taskText").value("Sample Task"));
+
+ verify(taskService).getAllTasks();
+ }
+
+ @Test
+ void getUserTasks_ValidUserId_ReturnsOk() throws Exception {
+ when(taskService.getUserTasks(1L)).thenReturn(List.of(task));
+
+ mockMvc.perform(get("/api/tasks/user/1"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].userId").value(1));
+
+ verify(taskService).getUserTasks(1L);
+ }
+
+ @Test
+ void createTask_ValidTask_ReturnsCreated() throws Exception {
+ when(taskService.createTask(any(Task.class))).thenReturn(task);
+
+ mockMvc.perform(post("/api/tasks")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(task)))
+ .andExpect(status().isCreated())
+ .andExpect(jsonPath("$.taskText").value("Sample Task"));
+
+ verify(taskService).createTask(any(Task.class));
+ }
+
+ @Test
+ void deleteTask_ValidId_ReturnsNoContent() throws Exception {
+ doNothing().when(taskService).deleteTask(1L);
+
+ mockMvc.perform(delete("/api/tasks/1"))
+ .andExpect(status().isNoContent());
+
+ verify(taskService).deleteTask(1L);
+ }
+}
diff --git a/src/test/java/task/controller/UserControllerTest.java b/src/test/java/task/controller/UserControllerTest.java
new file mode 100644
index 0000000..3421299
--- /dev/null
+++ b/src/test/java/task/controller/UserControllerTest.java
@@ -0,0 +1,93 @@
+package task.controller;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mock;
+import org.mockito.InjectMocks;
+import org.mockito.MockitoAnnotations;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import task.model.User;
+import task.service.UserService;
+
+import java.util.List;
+import java.util.Optional;
+
+import static org.mockito.Mockito.*;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
+
+class UserControllerTest {
+
+ private MockMvc mockMvc;
+
+ @Mock
+ private UserService userService;
+
+ @InjectMocks
+ private UserController userController;
+
+ private ObjectMapper objectMapper;
+ private User user;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+ mockMvc = MockMvcBuilders.standaloneSetup(userController).build();
+ objectMapper = new ObjectMapper();
+
+ user = User.builder()
+ .userId(1L)
+ .login("testLogin")
+ .userName("testUser")
+ .email("test@mail.com")
+ .build();
+ }
+
+ @Test
+ void getAllUsers_WhenUsersExist_ReturnsOkAndUserList() throws Exception {
+ when(userService.getAllUsers()).thenReturn(List.of(user));
+
+ mockMvc.perform(get("/api/users"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$[0].userName").value("testUser"));
+
+ verify(userService).getAllUsers();
+ }
+
+ @Test
+ void register_ValidUser_ReturnsCreated() throws Exception {
+ when(userService.register(any(User.class))).thenReturn(user);
+
+ mockMvc.perform(post("/api/users")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(user)))
+ .andExpect(status().isCreated())
+ .andExpect(jsonPath("$.login").value("testLogin"));
+
+ verify(userService).register(any(User.class));
+ }
+
+ @Test
+ void getUserById_ExistingId_ReturnsOkAndUser() throws Exception {
+ when(userService.getUserById(1L)).thenReturn(Optional.of(user));
+
+ mockMvc.perform(get("/api/users/1"))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.userName").value("testUser"));
+
+ verify(userService).getUserById(1L);
+ }
+
+ @Test
+ void getUserById_NonExistingId_ReturnsNotFound() throws Exception {
+ when(userService.getUserById(99L)).thenReturn(Optional.empty());
+
+ mockMvc.perform(get("/api/users/99"))
+ .andExpect(status().isNotFound());
+
+ verify(userService).getUserById(99L);
+ }
+}
diff --git a/src/test/java/task/repository/impl/NotificationRepositoryImplTest.java b/src/test/java/task/repository/impl/NotificationRepositoryImplTest.java
new file mode 100644
index 0000000..9aedc68
--- /dev/null
+++ b/src/test/java/task/repository/impl/NotificationRepositoryImplTest.java
@@ -0,0 +1,137 @@
+package task.repository.impl;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import task.model.Notification;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class NotificationRepositoryImplTest {
+
+ private NotificationRepositoryImpl repository;
+ private Notification notification;
+
+ @BeforeEach
+ void setUp() {
+ repository = new NotificationRepositoryImpl();
+
+ notification = Notification.builder()
+ .text("Reminder about task")
+ .taskId(1L)
+ .userId(10L)
+ .isRead(false)
+ .build();
+ }
+
+ @Test
+ void save_NewNotification_AssignsIdAndStoresNotification() {
+ // Act
+ Notification saved = repository.save(notification);
+
+ // Assert
+ assertNotNull(saved.getNotificationId(), "Id должен быть присвоен");
+ assertEquals(1, repository.findAll().size(), "Ожидаем 1 уведомление в репозитории");
+ }
+
+ @Test
+ void findByUserId_UserHasNotifications_ReturnsCorrectList() {
+ // Arrange
+ repository.save(notification);
+ repository.save(Notification.builder()
+ .text("Another one")
+ .taskId(2L)
+ .userId(20L)
+ .isRead(false)
+ .build());
+
+ // Act
+ List list = repository.findByUserId(10L);
+
+ // Assert
+ assertEquals(1, list.size(), "Ожидаем 1 уведомление для userId=10");
+ assertEquals("Reminder about task", list.get(0).getText());
+ }
+
+ @Test
+ void findByUserId_UserHasNoNotifications_ReturnsEmptyList() {
+ // Arrange
+ repository.save(notification);
+
+ // Act
+ List list = repository.findByUserId(999L);
+
+ // Assert
+ assertTrue(list.isEmpty(), "Список должен быть пуст для неизвестного пользователя");
+ }
+
+ @Test
+ void findByUserIdAndIsReadFalse_HasUnread_ReturnsOnlyUnread() {
+ // Arrange
+ repository.save(notification); // unread
+ repository.save(Notification.builder()
+ .text("Read message")
+ .taskId(2L)
+ .userId(10L)
+ .isRead(true)
+ .build());
+
+ // Act
+ List unread = repository.findByUserIdAndIsReadFalse(10L);
+
+ // Assert
+ assertEquals(1, unread.size(), "Ожидаем только одно непрочитанное уведомление");
+ assertFalse(unread.get(0).getIsRead(), "Уведомление должно быть непрочитанным");
+ }
+
+ @Test
+ void findByUserIdAndIsReadFalse_NoUnread_ReturnsEmptyList() {
+ // Arrange
+ repository.save(Notification.builder()
+ .text("Read message")
+ .taskId(3L)
+ .userId(15L)
+ .isRead(true)
+ .build());
+
+ // Act
+ List unread = repository.findByUserIdAndIsReadFalse(15L);
+
+ // Assert
+ assertTrue(unread.isEmpty(), "Ожидаем пустой список при отсутствии непрочитанных");
+ }
+
+ @Test
+ void save_ExistingNotificationId_UpdatesStoredNotification() {
+ // Arrange
+ Notification saved = repository.save(notification);
+ saved.setText("Updated text");
+
+ // Act
+ repository.save(saved);
+
+ // Assert
+ List all = repository.findAll();
+ assertEquals(1, all.size());
+ assertEquals("Updated text", all.get(0).getText(), "Текст должен быть обновлён");
+ }
+
+ @Test
+ void findAll_MultipleNotifications_ReturnsAll() {
+ // Arrange
+ repository.save(notification);
+ repository.save(Notification.builder()
+ .text("Second note")
+ .taskId(2L)
+ .userId(10L)
+ .isRead(false)
+ .build());
+
+ // Act
+ List all = repository.findAll();
+
+ // Assert
+ assertEquals(2, all.size(), "Ожидаем 2 уведомления");
+ }
+}
diff --git a/src/test/java/task/repository/impl/TaskRepositoryImplTest.java b/src/test/java/task/repository/impl/TaskRepositoryImplTest.java
new file mode 100644
index 0000000..33ead9d
--- /dev/null
+++ b/src/test/java/task/repository/impl/TaskRepositoryImplTest.java
@@ -0,0 +1,95 @@
+package task.repository.impl;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import task.model.Task;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class TaskRepositoryImplTest {
+
+ private TaskRepositoryImpl repository;
+ private Task task;
+ private static final LocalDateTime DATE_NOW = LocalDateTime.now();
+
+ @BeforeEach
+ void setUp() {
+ repository = new TaskRepositoryImpl();
+
+ task = Task.builder()
+ .taskText("Test task 1")
+ .userId(1L)
+ .actionDate(DATE_NOW.plusDays(2))
+ .build();
+ }
+
+ @Test
+ void save_NewTask_AssignsIdAndStoresTask() {
+ Task saved = repository.save(task);
+
+ assertNotNull(saved.getTaskId(), "Id должен быть назначен");
+ assertEquals(1, repository.findAllIsDeleteFalse().size(), "В репозитории должен быть 1 элемент");
+ }
+
+ @Test
+ void findByUserIdAndIsDeleteFalse_ExistingTasks_ReturnsCorrectTasks() {
+ repository.save(task);
+ repository.save(Task.builder()
+ .taskText("Test task 2")
+ .userId(2L)
+ .actionDate(DATE_NOW.plusDays(3))
+ .build()
+ );
+
+ List tasks = repository.findByUserIdAndIsDeleteFalse(1L);
+
+ assertEquals(1, tasks.size());
+ assertEquals("Test task 1", tasks.get(0).getTaskText());
+ }
+
+ @Test
+ void findByUserIdAndIsDeleteFalse_NoTasksForUser_ReturnsEmptyList() {
+ // не сохраняем задачи для userId=99
+ List tasks = repository.findByUserIdAndIsDeleteFalse(99L);
+ assertTrue(tasks.isEmpty(), "Ожидаем пустой список если задач нет для заданного пользователя");
+ }
+
+ @Test
+ void findByUserIdAndIsCompleteFalseAndIsDeleteFalse_OnlyIncomplete_ReturnsPending() {
+ Task completedTask = Task.builder()
+ .taskText("Completed task")
+ .userId(1L)
+ .actionDate(DATE_NOW.plusDays(3))
+ .isComplete(true) // помечена как выполненная
+ .build();
+
+ repository.save(task); // incomplete
+ repository.save(completedTask); // complete
+
+ List pending = repository.findByUserIdAndIsCompleteFalseAndIsDeleteFalse(1L);
+
+ assertEquals(1, pending.size());
+ assertEquals("Test task 1", pending.get(0).getTaskText());
+ }
+
+ @Test
+ void markAsDeleted_TaskExists_SetsIsDeleteTrue() {
+ Task saved = repository.save(task);
+ repository.markAsDeleted(saved.getTaskId());
+
+ // findById должен вернуть empty, т.к. task помечен как удаленный
+ assertTrue(repository.findByIdAndIsDeleteFalse(saved.getTaskId()).isEmpty());
+ }
+
+ @Test
+ void markAsDeleted_NonExistingTask_NoExceptionAndStateUnchanged() {
+ // не должно кидать исключения при пометке несуществующего id
+ repository.markAsDeleted(999L);
+ // репозиторий по-прежнему пуст
+ assertTrue(repository.findAllIsDeleteFalse().isEmpty());
+ }
+}
diff --git a/src/test/java/task/repository/impl/UserRepositoryImplTest.java b/src/test/java/task/repository/impl/UserRepositoryImplTest.java
new file mode 100644
index 0000000..baf909a
--- /dev/null
+++ b/src/test/java/task/repository/impl/UserRepositoryImplTest.java
@@ -0,0 +1,118 @@
+package task.repository.impl;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import task.model.User;
+
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+class UserRepositoryImplTest {
+
+ private UserRepositoryImpl repository;
+ private User user;
+
+ @BeforeEach
+ void setUp() {
+ repository = new UserRepositoryImpl();
+
+ user = User.builder()
+ .login("login1")
+ .password("pass123")
+ .email("user1@mail.com")
+ .userName("user1Name")
+ .build();
+ }
+
+ @Test
+ void save_NewUser_AssignsIdAndStoresUser() {
+ // Act
+ User saved = repository.save(user);
+
+ // Assert
+ assertNotNull(saved.getUserId(), "Id должен быть назначен");
+ assertEquals(1, repository.findAll().size(), "В репозитории должен быть 1 пользователь");
+ }
+
+ @Test
+ void findByUserName_UserExists_ReturnsUser() {
+ // Arrange
+ repository.save(user);
+
+ // Act
+ Optional result = repository.findByUserName("user1Name");
+
+ // Assert
+ assertTrue(result.isPresent(), "Пользователь должен быть найден");
+ assertEquals("login1", result.get().getLogin());
+ }
+
+ @Test
+ void findByUserName_UserNotExists_ReturnsEmpty() {
+ // Arrange
+ repository.save(user);
+
+ // Act
+ Optional result = repository.findByUserName("unknown");
+
+ // Assert
+ assertTrue(result.isEmpty(), "Ожидаем пустой Optional");
+ }
+
+ @Test
+ void findById_ExistingId_ReturnsUser() {
+ // Arrange
+ User saved = repository.save(user);
+
+ // Act
+ Optional found = repository.findById(saved.getUserId());
+
+ // Assert
+ assertTrue(found.isPresent(), "Пользователь должен быть найден");
+ assertEquals(saved.getUserName(), found.get().getUserName());
+ }
+
+ @Test
+ void findById_NonExistingId_ReturnsEmpty() {
+ // Act
+ Optional found = repository.findById(999L);
+
+ // Assert
+ assertTrue(found.isEmpty(), "Ожидаем Optional.empty для несуществующего id");
+ }
+
+ @Test
+ void findAll_WhenMultipleUsersExist_ReturnsAllUsers() {
+ // Arrange
+ repository.save(user);
+ repository.save(User.builder()
+ .login("login2")
+ .password("pass456")
+ .email("user2@mail.com")
+ .userName("user2Name")
+ .build());
+
+ // Act
+ List all = repository.findAll();
+
+ // Assert
+ assertEquals(2, all.size(), "Ожидаем 2 пользователя");
+ }
+
+ @Test
+ void save_UserWithExistingId_OverwritesExistingUser() {
+ // Arrange
+ User saved = repository.save(user);
+ saved.setEmail("updated@mail.com");
+
+ // Act
+ repository.save(saved);
+
+ // Assert
+ Optional found = repository.findById(saved.getUserId());
+ assertTrue(found.isPresent());
+ assertEquals("updated@mail.com", found.get().getEmail(), "Email должен быть обновлён");
+ }
+}
diff --git a/src/test/java/task/service/impl/NotificationServiceImplTest.java b/src/test/java/task/service/impl/NotificationServiceImplTest.java
new file mode 100644
index 0000000..6ad9108
--- /dev/null
+++ b/src/test/java/task/service/impl/NotificationServiceImplTest.java
@@ -0,0 +1,91 @@
+package task.service.impl;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import task.model.Notification;
+import task.repository.NotificationRepository;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+class NotificationServiceImplTest {
+
+ @Mock
+ private NotificationRepository notificationRepository;
+
+ @InjectMocks
+ private NotificationServiceImpl notificationService;
+
+ private Notification notification;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+
+ notification = Notification.builder()
+ .notificationId(1L)
+ .text("Task reminder")
+ .taskId(1L)
+ .userId(10L)
+ .isRead(false)
+ .build();
+ }
+
+ @Test
+ void getAllNotifications_WhenExist_ReturnsList() {
+ when(notificationRepository.findAll()).thenReturn(List.of(notification));
+
+ List result = notificationService.getAllNotifications();
+
+ assertEquals(1, result.size());
+ assertEquals("Task reminder", result.get(0).getText());
+ verify(notificationRepository).findAll();
+ }
+
+ @Test
+ void getUserNotifications_ValidUserId_ReturnsNotifications() {
+ when(notificationRepository.findByUserId(10L)).thenReturn(List.of(notification));
+
+ List result = notificationService.getUserNotifications(10L);
+
+ assertEquals(1, result.size());
+ verify(notificationRepository).findByUserId(10L);
+ }
+
+ @Test
+ void getUserNotifications_NoNotifications_ReturnsEmptyList() {
+ when(notificationRepository.findByUserId(99L)).thenReturn(List.of());
+
+ List result = notificationService.getUserNotifications(99L);
+
+ assertTrue(result.isEmpty());
+ verify(notificationRepository).findByUserId(99L);
+ }
+
+ @Test
+ void getUserNotificationsUnread_HasUnread_ReturnsOnlyUnread() {
+ when(notificationRepository.findByUserIdAndIsReadFalse(10L)).thenReturn(List.of(notification));
+
+ List unread = notificationService.getUserNotificationsUnread(10L);
+
+ assertEquals(1, unread.size());
+ assertFalse(unread.get(0).getIsRead());
+ verify(notificationRepository).findByUserIdAndIsReadFalse(10L);
+ }
+
+ @Test
+ void createNotification_ValidNotification_SavesAndReturns() {
+ when(notificationRepository.save(notification)).thenReturn(notification);
+
+ Notification created = notificationService.createNotification(notification);
+
+ assertNotNull(created);
+ assertEquals("Task reminder", created.getText());
+ verify(notificationRepository).save(notification);
+ }
+}
diff --git a/src/test/java/task/service/impl/TaskServiceImplTest.java b/src/test/java/task/service/impl/TaskServiceImplTest.java
new file mode 100644
index 0000000..26cfaf0
--- /dev/null
+++ b/src/test/java/task/service/impl/TaskServiceImplTest.java
@@ -0,0 +1,88 @@
+package task.service.impl;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import task.model.Task;
+import task.repository.TaskRepository;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+class TaskServiceImplTest {
+
+ @Mock
+ private TaskRepository taskRepository;
+
+ @InjectMocks
+ private TaskServiceImpl taskService;
+
+ private Task task;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+
+ task = Task.builder()
+ .taskId(1L)
+ .taskText("Test task")
+ .userId(1L)
+ .createDate(LocalDateTime.now())
+ .build();
+ }
+
+ @Test
+ void getAllTasks_WhenTasksExist_ReturnsTaskList() {
+ when(taskRepository.findAllIsDeleteFalse()).thenReturn(List.of(task));
+
+ List result = taskService.getAllTasks();
+
+ assertEquals(1, result.size());
+ assertEquals("Test task", result.get(0).getTaskText());
+ verify(taskRepository).findAllIsDeleteFalse();
+ }
+
+ @Test
+ void getUserTasks_ValidUserId_ReturnsTasks() {
+ when(taskRepository.findByUserIdAndIsDeleteFalse(1L)).thenReturn(List.of(task));
+
+ List result = taskService.getUserTasks(1L);
+
+ assertEquals(1, result.size());
+ verify(taskRepository).findByUserIdAndIsDeleteFalse(1L);
+ }
+
+ @Test
+ void getUserTasksPending_OnlyIncompleteTasks_ReturnsPending() {
+ when(taskRepository.findByUserIdAndIsCompleteFalseAndIsDeleteFalse(1L)).thenReturn(List.of(task));
+
+ List result = taskService.getUserTasksPending(1L);
+
+ assertEquals(1, result.size());
+ assertFalse(result.get(0).getIsComplete());
+ verify(taskRepository).findByUserIdAndIsCompleteFalseAndIsDeleteFalse(1L);
+ }
+
+ @Test
+ void createTask_ValidTask_SavesTask() {
+ when(taskRepository.save(task)).thenReturn(task);
+
+ Task created = taskService.createTask(task);
+
+ assertNotNull(created);
+ assertEquals("Test task", created.getTaskText());
+ verify(taskRepository).save(task);
+ }
+
+ @Test
+ void deleteTask_ValidId_CallsRepositoryMarkAsDeleted() {
+ taskService.deleteTask(1L);
+
+ verify(taskRepository).markAsDeleted(1L);
+ }
+}
diff --git a/src/test/java/task/service/impl/UserServiceImplTest.java b/src/test/java/task/service/impl/UserServiceImplTest.java
new file mode 100644
index 0000000..c72fccf
--- /dev/null
+++ b/src/test/java/task/service/impl/UserServiceImplTest.java
@@ -0,0 +1,102 @@
+package task.service.impl;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import task.model.User;
+import task.repository.UserRepository;
+
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+class UserServiceImplTest {
+
+ @Mock
+ private UserRepository userRepository;
+
+ @InjectMocks
+ private UserServiceImpl userService;
+
+ private User user;
+
+ @BeforeEach
+ void setUp() {
+ MockitoAnnotations.openMocks(this);
+
+ user = User.builder()
+ .userId(1L)
+ .login("userLogin")
+ .password("12345")
+ .userName("userName")
+ .email("user@mail.com")
+ .build();
+ }
+
+ @Test
+ void getAllUsers_WhenUsersExist_ReturnsUserList() {
+ when(userRepository.findAll()).thenReturn(List.of(user));
+
+ List result = userService.getAllUsers();
+
+ assertEquals(1, result.size());
+ assertEquals("userName", result.get(0).getUserName());
+ verify(userRepository).findAll();
+ }
+
+ @Test
+ void register_ValidUser_SavesUser() {
+ when(userRepository.save(any(User.class))).thenReturn(user);
+
+ User saved = userService.register(user);
+
+ assertNotNull(saved);
+ assertEquals("userLogin", saved.getLogin());
+ verify(userRepository).save(user);
+ }
+
+ @Test
+ void login_ValidCredentials_ReturnsUser() {
+ when(userRepository.findByUserName("userName")).thenReturn(Optional.of(user));
+
+ Optional result = userService.login("userName", "12345");
+
+ assertTrue(result.isPresent());
+ assertEquals("userLogin", result.get().getLogin());
+ verify(userRepository).findByUserName("userName");
+ }
+
+ @Test
+ void login_InvalidPassword_ReturnsEmpty() {
+ when(userRepository.findByUserName("userName")).thenReturn(Optional.of(user));
+
+ Optional result = userService.login("userName", "wrongPass");
+
+ assertTrue(result.isEmpty());
+ verify(userRepository).findByUserName("userName");
+ }
+
+ @Test
+ void getUserById_ExistingId_ReturnsUser() {
+ when(userRepository.findById(1L)).thenReturn(Optional.of(user));
+
+ Optional result = userService.getUserById(1L);
+
+ assertTrue(result.isPresent());
+ assertEquals("userLogin", result.get().getLogin());
+ verify(userRepository).findById(1L);
+ }
+
+ @Test
+ void getUserById_NonExistingId_ReturnsEmpty() {
+ when(userRepository.findById(99L)).thenReturn(Optional.empty());
+
+ Optional result = userService.getUserById(99L);
+
+ assertTrue(result.isEmpty());
+ }
+}
diff --git a/target/classes/task/repository/TaskRepository.class b/target/classes/task/repository/TaskRepository.class
index 3bd4526..fdb9c7f 100644
Binary files a/target/classes/task/repository/TaskRepository.class and b/target/classes/task/repository/TaskRepository.class differ
diff --git a/target/classes/task/repository/impl/TaskRepositoryImpl.class b/target/classes/task/repository/impl/TaskRepositoryImpl.class
index 15cf135..397df04 100644
Binary files a/target/classes/task/repository/impl/TaskRepositoryImpl.class and b/target/classes/task/repository/impl/TaskRepositoryImpl.class differ
diff --git a/target/test-classes/task/controller/NotificationControllerTest.class b/target/test-classes/task/controller/NotificationControllerTest.class
new file mode 100644
index 0000000..26ef8d0
Binary files /dev/null and b/target/test-classes/task/controller/NotificationControllerTest.class differ
diff --git a/target/test-classes/task/controller/TaskControllerTest.class b/target/test-classes/task/controller/TaskControllerTest.class
new file mode 100644
index 0000000..76a1569
Binary files /dev/null and b/target/test-classes/task/controller/TaskControllerTest.class differ
diff --git a/target/test-classes/task/controller/UserControllerTest.class b/target/test-classes/task/controller/UserControllerTest.class
new file mode 100644
index 0000000..20a2a36
Binary files /dev/null and b/target/test-classes/task/controller/UserControllerTest.class differ
diff --git a/target/test-classes/task/repository/impl/NotificationRepositoryImplTest.class b/target/test-classes/task/repository/impl/NotificationRepositoryImplTest.class
new file mode 100644
index 0000000..3da8c44
Binary files /dev/null and b/target/test-classes/task/repository/impl/NotificationRepositoryImplTest.class differ
diff --git a/target/test-classes/task/repository/impl/TaskRepositoryImplTest.class b/target/test-classes/task/repository/impl/TaskRepositoryImplTest.class
new file mode 100644
index 0000000..6a34a06
Binary files /dev/null and b/target/test-classes/task/repository/impl/TaskRepositoryImplTest.class differ
diff --git a/target/test-classes/task/repository/impl/UserRepositoryImplTest.class b/target/test-classes/task/repository/impl/UserRepositoryImplTest.class
new file mode 100644
index 0000000..395f821
Binary files /dev/null and b/target/test-classes/task/repository/impl/UserRepositoryImplTest.class differ
diff --git a/target/test-classes/task/service/impl/NotificationServiceImplTest.class b/target/test-classes/task/service/impl/NotificationServiceImplTest.class
new file mode 100644
index 0000000..00e1345
Binary files /dev/null and b/target/test-classes/task/service/impl/NotificationServiceImplTest.class differ
diff --git a/target/test-classes/task/service/impl/TaskServiceImplTest.class b/target/test-classes/task/service/impl/TaskServiceImplTest.class
new file mode 100644
index 0000000..8cbb5b3
Binary files /dev/null and b/target/test-classes/task/service/impl/TaskServiceImplTest.class differ
diff --git a/target/test-classes/task/service/impl/UserServiceImplTest.class b/target/test-classes/task/service/impl/UserServiceImplTest.class
new file mode 100644
index 0000000..693fff7
Binary files /dev/null and b/target/test-classes/task/service/impl/UserServiceImplTest.class differ