From 8286fc711e3b949793c6bf87cd41c60847dba70e Mon Sep 17 00:00:00 2001 From: drewandrewd Date: Tue, 22 Apr 2025 22:26:34 +0500 Subject: [PATCH 1/3] Added test for controller, service and mapper --- .../controller/TaskControllerTest.java | 104 +++++++++++ .../integration/PostgresContainer.java | 21 +++ .../schoolproject/mapper/MainMapperTest.java | 47 +++++ .../service/TaskServiceTest.java | 162 ++++++++++++++++++ 4 files changed, 334 insertions(+) create mode 100644 src/test/java/com/example/schoolproject/controller/TaskControllerTest.java create mode 100644 src/test/java/com/example/schoolproject/integration/PostgresContainer.java create mode 100644 src/test/java/com/example/schoolproject/mapper/MainMapperTest.java create mode 100644 src/test/java/com/example/schoolproject/service/TaskServiceTest.java diff --git a/src/test/java/com/example/schoolproject/controller/TaskControllerTest.java b/src/test/java/com/example/schoolproject/controller/TaskControllerTest.java new file mode 100644 index 0000000..fddbe7b --- /dev/null +++ b/src/test/java/com/example/schoolproject/controller/TaskControllerTest.java @@ -0,0 +1,104 @@ +package com.example.schoolproject.controller; + +import com.example.schoolproject.dto.TaskDTO; +import com.example.schoolproject.entity.Task; +import com.example.schoolproject.entity.TaskStatus; +import com.example.schoolproject.integration.PostgresContainer; +import com.example.schoolproject.repository.TaskRepository; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +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.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +public class TaskControllerTest extends PostgresContainer { + + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + @Autowired + private MockMvc mockMvc; + + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private TaskRepository repository; + + private Long savedTaskId; + + @BeforeEach + void setUp() { + repository.deleteAll(); + Task saved = repository.save(getTask()); + savedTaskId = saved.getId(); + } + + private Task getTask() { + return new Task(null, "title", "description", 10L, TaskStatus.TODO); + } + + private TaskDTO getTaskDTO() { + return new TaskDTO("title", "description", 10L, TaskStatus.TODO); + } + + @Test + void shouldReturnAllTasks() throws Exception { + mockMvc.perform(get("/tasks")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].title").value("title")) + .andExpect(jsonPath("$[0].description").value("description")) + .andExpect(jsonPath("$[0].userId").value(10L)); + } + + @Test + void shouldReturnTaskById() throws Exception { + mockMvc.perform(get("/tasks/" + savedTaskId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("title")) + .andExpect(jsonPath("$.description").value("description")) + .andExpect(jsonPath("$.userId").value(10L)); + } + + @Test + void shouldCreateTask() throws Exception { + mockMvc.perform(post("/tasks") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(getTaskDTO()))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("title")) + .andExpect(jsonPath("$.description").value("description")) + .andExpect(jsonPath("$.userId").value(10L)); + } + + @Test + void shouldUpdateTask() throws Exception { + mockMvc.perform(put("/tasks/" + savedTaskId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(getTaskDTO()))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("title")) + .andExpect(jsonPath("$.description").value("description")) + .andExpect(jsonPath("$.userId").value(10L)); + } + + @Test + void shouldDeleteTask() throws Exception { + mockMvc.perform(delete("/tasks/" + savedTaskId)) + .andExpect(status().isNoContent()); + } + + @Test + void shouldReturnNotFoundWhenTaskDoesNotExist() throws Exception { + mockMvc.perform(get("/tasks/99999")) + .andExpect(status().isNotFound()) + .andExpect(content().string("Task with id 99999 is not found")); + } +} diff --git a/src/test/java/com/example/schoolproject/integration/PostgresContainer.java b/src/test/java/com/example/schoolproject/integration/PostgresContainer.java new file mode 100644 index 0000000..8b38a1f --- /dev/null +++ b/src/test/java/com/example/schoolproject/integration/PostgresContainer.java @@ -0,0 +1,21 @@ +package com.example.schoolproject.integration; + +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@Testcontainers +public class PostgresContainer { + + @Container + public static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:16"); + + @DynamicPropertySource + public static void properties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl); + registry.add("spring.datasource.username", postgres::getUsername); + registry.add("spring.datasource.password", postgres::getPassword); + } +} diff --git a/src/test/java/com/example/schoolproject/mapper/MainMapperTest.java b/src/test/java/com/example/schoolproject/mapper/MainMapperTest.java new file mode 100644 index 0000000..a77e219 --- /dev/null +++ b/src/test/java/com/example/schoolproject/mapper/MainMapperTest.java @@ -0,0 +1,47 @@ +package com.example.schoolproject.mapper; + +import com.example.schoolproject.dto.TaskDTO; +import com.example.schoolproject.dto.TaskStatusUpdateDTO; +import com.example.schoolproject.entity.Task; +import com.example.schoolproject.entity.TaskStatus; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mapstruct.factory.Mappers; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class MainMapperTest { + + private MainMapper mapper = Mappers.getMapper(MainMapper.class); + + private Task getCreatedTask() { + return new Task(1L, "title", "description", 10L, TaskStatus.TODO); + } + + private TaskDTO getCreatedTaskDTO() { + return new TaskDTO("title", "description", 10L, TaskStatus.TODO); + } + + private TaskStatusUpdateDTO getTaskStatusUpdateDTO() { + return new TaskStatusUpdateDTO(1L, TaskStatus.TODO); + } + + @Test + void shouldReturnTaskDTO() { + TaskDTO result = mapper.toDTO(getCreatedTask()); + Assertions.assertEquals(result, getCreatedTaskDTO()); + } + + @Test + void shouldReturnTaskEntity() { + Task result = mapper.toEntity(getCreatedTaskDTO()); + Assertions.assertEquals(result, getCreatedTask()); + } + + @Test + void shouldReturnTaskStatusUpdateDTO() { + TaskStatusUpdateDTO result = mapper.toStatusUpdateDTO(getCreatedTask()); + Assertions.assertEquals(result, getTaskStatusUpdateDTO()); + } +} diff --git a/src/test/java/com/example/schoolproject/service/TaskServiceTest.java b/src/test/java/com/example/schoolproject/service/TaskServiceTest.java new file mode 100644 index 0000000..9d46905 --- /dev/null +++ b/src/test/java/com/example/schoolproject/service/TaskServiceTest.java @@ -0,0 +1,162 @@ +package com.example.schoolproject.service; + +import com.example.schoolproject.dto.TaskDTO; +import com.example.schoolproject.dto.TaskStatusUpdateDTO; +import com.example.schoolproject.entity.Task; +import com.example.schoolproject.entity.TaskStatus; +import com.example.schoolproject.exception.TaskNotFoundException; +import com.example.schoolproject.kafka.KafkaTaskProducer; +import com.example.schoolproject.mapper.MainMapper; +import com.example.schoolproject.repository.TaskRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class TaskServiceTest { + + @Mock + private TaskRepository taskRepository; + + @Mock + private KafkaTaskProducer kafkaTaskProducer; + + @Mock + private MainMapper mapper; + + private static final Long ID = 1L; + private static final String TASKS_NOT_FOUND = "Tasks are not found"; + private static final String TASK_NOT_FOUND = "Task with id " + ID + " is not found"; + + @BeforeEach + void setUp() { + } + + private Task getCreatedTask() { + return new Task(ID, "title", "description", 10L, TaskStatus.TODO); + } + + private TaskDTO getCreatedTaskDTO() { + return new TaskDTO("title", "description", 10L, TaskStatus.TODO); + } + + private Task getUpdatedTask() { + return new Task(ID, "newTitle", "newDescription", 11L, TaskStatus.DONE); + } + + private TaskDTO getUpdatedTaskDTO() { + return new TaskDTO("newTitle", "newDescription", 11L, TaskStatus.DONE); + } + + private TaskStatusUpdateDTO getTaskStatusUpdateDTO() { + return new TaskStatusUpdateDTO(ID, TaskStatus.DONE); + } + + private TaskService getTaskService() { + return new TaskServiceImpl(taskRepository, mapper, kafkaTaskProducer); + } + + @Test + void shouldReturnTaskByIdWhenExist() { + Task task = getCreatedTask(); + TaskDTO taskDTO = getCreatedTaskDTO(); + TaskService service = getTaskService(); + when(taskRepository.findById(ID)).thenReturn(Optional.of(task)); + when(mapper.toDTO(task)).thenReturn(taskDTO); + TaskDTO result = service.getTaskById(ID); + Assertions.assertNotNull(result); + assertEquals(taskDTO, result); + verify(taskRepository, times(1)).findById(ID); + } + + @Test + void shouldTrowExceptionWhenTaskNotFoundById() { + TaskService service = getTaskService(); + when(taskRepository.findById(ID)).thenReturn(Optional.empty()); + TaskNotFoundException exception = Assertions.assertThrows(TaskNotFoundException.class, () -> service.getTaskById(ID)); + verify(taskRepository).findById(any()); + assertEquals(TASK_NOT_FOUND, exception.getMessage()); + } + + @Test + void shouldReturnAllTasksWhenExist() { + Task task = getCreatedTask(); + TaskDTO taskDTO = getCreatedTaskDTO(); + TaskService service = getTaskService(); + when(taskRepository.findAll()).thenReturn(List.of(task)); + when(mapper.toDTO(task)).thenReturn(taskDTO); + List result = service.getAllTasks(); + Assertions.assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(taskDTO, result.get(0)); + verify(taskRepository, times(1)).findAll(); + } + + @Test + void shouldThrowExceptionWhenTasksNotFound() { + TaskService service = getTaskService(); + when(taskRepository.findAll()).thenReturn(Collections.emptyList()); + TaskNotFoundException exception = Assertions.assertThrows(TaskNotFoundException.class, () -> service.getAllTasks()); + verify(taskRepository).findAll(); + assertEquals(TASKS_NOT_FOUND, exception.getMessage()); + } + + @Test + void shouldDeleteTaskWhenExist() { + TaskService service = getTaskService(); + when(taskRepository.existsById(ID)).thenReturn(true); + service.deleteTask(ID); + verify(taskRepository, times(1)).existsById(ID); + verify(taskRepository, times(1)).deleteById(ID); + } + + @Test + void shouldThrowExceptionInsteadDeleting() { + TaskService service = getTaskService(); + when(taskRepository.existsById(ID)).thenReturn(false); + TaskNotFoundException exception = Assertions.assertThrows(TaskNotFoundException.class, () -> service.deleteTask(ID)); + verify(taskRepository).existsById(ID); + verify(taskRepository, never()).deleteById(any()); + assertEquals(TASK_NOT_FOUND, exception.getMessage()); + } + + @Test + void shouldCreateTask() { + Task task = getCreatedTask(); + TaskDTO taskDTO = getCreatedTaskDTO(); + TaskService service = getTaskService(); + when(mapper.toEntity(taskDTO)).thenReturn(task); + when(taskRepository.save(task)).thenReturn(task); + when(mapper.toDTO(task)).thenReturn(taskDTO); + TaskDTO result = service.createTask(taskDTO); + assertEquals(taskDTO, result); + verify(taskRepository, times(1)).save(task); + } + + @Test + void shouldUpdateTask() { + Task task = getCreatedTask(); + TaskService service = getTaskService(); + Task updatedTask = getUpdatedTask(); + TaskDTO updatedTaskDTO = getUpdatedTaskDTO(); + TaskStatusUpdateDTO taskStatusUpdateDTO = getTaskStatusUpdateDTO(); + when(taskRepository.findById(ID)).thenReturn(Optional.of(task)); + when(taskRepository.save(any(Task.class))).thenReturn(updatedTask); + when(mapper.toDTO(updatedTask)).thenReturn(updatedTaskDTO); + when(mapper.toStatusUpdateDTO(updatedTask)).thenReturn(taskStatusUpdateDTO); + TaskDTO result = service.updateTask(task.getId(), updatedTaskDTO); + assertEquals(updatedTaskDTO, result); + verify(taskRepository, times(1)).save(updatedTask); + verify(kafkaTaskProducer).sendTo(any(), eq(taskStatusUpdateDTO)); + } +} From f08cc4301fffc5c78ff976ce58c4b2991daa35d0 Mon Sep 17 00:00:00 2001 From: drewandrewd Date: Tue, 22 Apr 2025 22:32:41 +0500 Subject: [PATCH 2/3] Added test for controller, service and mapper --- .../controller/TaskControllerTest.java | 104 ----------- .../integration/PostgresContainer.java | 21 --- .../schoolproject/mapper/MainMapperTest.java | 47 ----- .../service/TaskServiceTest.java | 162 ------------------ 4 files changed, 334 deletions(-) delete mode 100644 src/test/java/com/example/schoolproject/controller/TaskControllerTest.java delete mode 100644 src/test/java/com/example/schoolproject/integration/PostgresContainer.java delete mode 100644 src/test/java/com/example/schoolproject/mapper/MainMapperTest.java delete mode 100644 src/test/java/com/example/schoolproject/service/TaskServiceTest.java diff --git a/src/test/java/com/example/schoolproject/controller/TaskControllerTest.java b/src/test/java/com/example/schoolproject/controller/TaskControllerTest.java deleted file mode 100644 index fddbe7b..0000000 --- a/src/test/java/com/example/schoolproject/controller/TaskControllerTest.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.example.schoolproject.controller; - -import com.example.schoolproject.dto.TaskDTO; -import com.example.schoolproject.entity.Task; -import com.example.schoolproject.entity.TaskStatus; -import com.example.schoolproject.integration.PostgresContainer; -import com.example.schoolproject.repository.TaskRepository; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.jupiter.api.BeforeEach; -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.context.SpringBootTest; -import org.springframework.http.MediaType; -import org.springframework.test.web.servlet.MockMvc; - -import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; - -@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -@AutoConfigureMockMvc -public class TaskControllerTest extends PostgresContainer { - - @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") - @Autowired - private MockMvc mockMvc; - - @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") - @Autowired - private ObjectMapper objectMapper; - - @Autowired - private TaskRepository repository; - - private Long savedTaskId; - - @BeforeEach - void setUp() { - repository.deleteAll(); - Task saved = repository.save(getTask()); - savedTaskId = saved.getId(); - } - - private Task getTask() { - return new Task(null, "title", "description", 10L, TaskStatus.TODO); - } - - private TaskDTO getTaskDTO() { - return new TaskDTO("title", "description", 10L, TaskStatus.TODO); - } - - @Test - void shouldReturnAllTasks() throws Exception { - mockMvc.perform(get("/tasks")) - .andExpect(status().isOk()) - .andExpect(jsonPath("$[0].title").value("title")) - .andExpect(jsonPath("$[0].description").value("description")) - .andExpect(jsonPath("$[0].userId").value(10L)); - } - - @Test - void shouldReturnTaskById() throws Exception { - mockMvc.perform(get("/tasks/" + savedTaskId)) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.title").value("title")) - .andExpect(jsonPath("$.description").value("description")) - .andExpect(jsonPath("$.userId").value(10L)); - } - - @Test - void shouldCreateTask() throws Exception { - mockMvc.perform(post("/tasks") - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(getTaskDTO()))) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.title").value("title")) - .andExpect(jsonPath("$.description").value("description")) - .andExpect(jsonPath("$.userId").value(10L)); - } - - @Test - void shouldUpdateTask() throws Exception { - mockMvc.perform(put("/tasks/" + savedTaskId) - .contentType(MediaType.APPLICATION_JSON) - .content(objectMapper.writeValueAsString(getTaskDTO()))) - .andExpect(status().isOk()) - .andExpect(jsonPath("$.title").value("title")) - .andExpect(jsonPath("$.description").value("description")) - .andExpect(jsonPath("$.userId").value(10L)); - } - - @Test - void shouldDeleteTask() throws Exception { - mockMvc.perform(delete("/tasks/" + savedTaskId)) - .andExpect(status().isNoContent()); - } - - @Test - void shouldReturnNotFoundWhenTaskDoesNotExist() throws Exception { - mockMvc.perform(get("/tasks/99999")) - .andExpect(status().isNotFound()) - .andExpect(content().string("Task with id 99999 is not found")); - } -} diff --git a/src/test/java/com/example/schoolproject/integration/PostgresContainer.java b/src/test/java/com/example/schoolproject/integration/PostgresContainer.java deleted file mode 100644 index 8b38a1f..0000000 --- a/src/test/java/com/example/schoolproject/integration/PostgresContainer.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.example.schoolproject.integration; - -import org.springframework.test.context.DynamicPropertyRegistry; -import org.springframework.test.context.DynamicPropertySource; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -@Testcontainers -public class PostgresContainer { - - @Container - public static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:16"); - - @DynamicPropertySource - public static void properties(DynamicPropertyRegistry registry) { - registry.add("spring.datasource.url", postgres::getJdbcUrl); - registry.add("spring.datasource.username", postgres::getUsername); - registry.add("spring.datasource.password", postgres::getPassword); - } -} diff --git a/src/test/java/com/example/schoolproject/mapper/MainMapperTest.java b/src/test/java/com/example/schoolproject/mapper/MainMapperTest.java deleted file mode 100644 index a77e219..0000000 --- a/src/test/java/com/example/schoolproject/mapper/MainMapperTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.example.schoolproject.mapper; - -import com.example.schoolproject.dto.TaskDTO; -import com.example.schoolproject.dto.TaskStatusUpdateDTO; -import com.example.schoolproject.entity.Task; -import com.example.schoolproject.entity.TaskStatus; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mapstruct.factory.Mappers; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class MainMapperTest { - - private MainMapper mapper = Mappers.getMapper(MainMapper.class); - - private Task getCreatedTask() { - return new Task(1L, "title", "description", 10L, TaskStatus.TODO); - } - - private TaskDTO getCreatedTaskDTO() { - return new TaskDTO("title", "description", 10L, TaskStatus.TODO); - } - - private TaskStatusUpdateDTO getTaskStatusUpdateDTO() { - return new TaskStatusUpdateDTO(1L, TaskStatus.TODO); - } - - @Test - void shouldReturnTaskDTO() { - TaskDTO result = mapper.toDTO(getCreatedTask()); - Assertions.assertEquals(result, getCreatedTaskDTO()); - } - - @Test - void shouldReturnTaskEntity() { - Task result = mapper.toEntity(getCreatedTaskDTO()); - Assertions.assertEquals(result, getCreatedTask()); - } - - @Test - void shouldReturnTaskStatusUpdateDTO() { - TaskStatusUpdateDTO result = mapper.toStatusUpdateDTO(getCreatedTask()); - Assertions.assertEquals(result, getTaskStatusUpdateDTO()); - } -} diff --git a/src/test/java/com/example/schoolproject/service/TaskServiceTest.java b/src/test/java/com/example/schoolproject/service/TaskServiceTest.java deleted file mode 100644 index 9d46905..0000000 --- a/src/test/java/com/example/schoolproject/service/TaskServiceTest.java +++ /dev/null @@ -1,162 +0,0 @@ -package com.example.schoolproject.service; - -import com.example.schoolproject.dto.TaskDTO; -import com.example.schoolproject.dto.TaskStatusUpdateDTO; -import com.example.schoolproject.entity.Task; -import com.example.schoolproject.entity.TaskStatus; -import com.example.schoolproject.exception.TaskNotFoundException; -import com.example.schoolproject.kafka.KafkaTaskProducer; -import com.example.schoolproject.mapper.MainMapper; -import com.example.schoolproject.repository.TaskRepository; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.Collections; -import java.util.List; -import java.util.Optional; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -public class TaskServiceTest { - - @Mock - private TaskRepository taskRepository; - - @Mock - private KafkaTaskProducer kafkaTaskProducer; - - @Mock - private MainMapper mapper; - - private static final Long ID = 1L; - private static final String TASKS_NOT_FOUND = "Tasks are not found"; - private static final String TASK_NOT_FOUND = "Task with id " + ID + " is not found"; - - @BeforeEach - void setUp() { - } - - private Task getCreatedTask() { - return new Task(ID, "title", "description", 10L, TaskStatus.TODO); - } - - private TaskDTO getCreatedTaskDTO() { - return new TaskDTO("title", "description", 10L, TaskStatus.TODO); - } - - private Task getUpdatedTask() { - return new Task(ID, "newTitle", "newDescription", 11L, TaskStatus.DONE); - } - - private TaskDTO getUpdatedTaskDTO() { - return new TaskDTO("newTitle", "newDescription", 11L, TaskStatus.DONE); - } - - private TaskStatusUpdateDTO getTaskStatusUpdateDTO() { - return new TaskStatusUpdateDTO(ID, TaskStatus.DONE); - } - - private TaskService getTaskService() { - return new TaskServiceImpl(taskRepository, mapper, kafkaTaskProducer); - } - - @Test - void shouldReturnTaskByIdWhenExist() { - Task task = getCreatedTask(); - TaskDTO taskDTO = getCreatedTaskDTO(); - TaskService service = getTaskService(); - when(taskRepository.findById(ID)).thenReturn(Optional.of(task)); - when(mapper.toDTO(task)).thenReturn(taskDTO); - TaskDTO result = service.getTaskById(ID); - Assertions.assertNotNull(result); - assertEquals(taskDTO, result); - verify(taskRepository, times(1)).findById(ID); - } - - @Test - void shouldTrowExceptionWhenTaskNotFoundById() { - TaskService service = getTaskService(); - when(taskRepository.findById(ID)).thenReturn(Optional.empty()); - TaskNotFoundException exception = Assertions.assertThrows(TaskNotFoundException.class, () -> service.getTaskById(ID)); - verify(taskRepository).findById(any()); - assertEquals(TASK_NOT_FOUND, exception.getMessage()); - } - - @Test - void shouldReturnAllTasksWhenExist() { - Task task = getCreatedTask(); - TaskDTO taskDTO = getCreatedTaskDTO(); - TaskService service = getTaskService(); - when(taskRepository.findAll()).thenReturn(List.of(task)); - when(mapper.toDTO(task)).thenReturn(taskDTO); - List result = service.getAllTasks(); - Assertions.assertNotNull(result); - assertEquals(1, result.size()); - assertEquals(taskDTO, result.get(0)); - verify(taskRepository, times(1)).findAll(); - } - - @Test - void shouldThrowExceptionWhenTasksNotFound() { - TaskService service = getTaskService(); - when(taskRepository.findAll()).thenReturn(Collections.emptyList()); - TaskNotFoundException exception = Assertions.assertThrows(TaskNotFoundException.class, () -> service.getAllTasks()); - verify(taskRepository).findAll(); - assertEquals(TASKS_NOT_FOUND, exception.getMessage()); - } - - @Test - void shouldDeleteTaskWhenExist() { - TaskService service = getTaskService(); - when(taskRepository.existsById(ID)).thenReturn(true); - service.deleteTask(ID); - verify(taskRepository, times(1)).existsById(ID); - verify(taskRepository, times(1)).deleteById(ID); - } - - @Test - void shouldThrowExceptionInsteadDeleting() { - TaskService service = getTaskService(); - when(taskRepository.existsById(ID)).thenReturn(false); - TaskNotFoundException exception = Assertions.assertThrows(TaskNotFoundException.class, () -> service.deleteTask(ID)); - verify(taskRepository).existsById(ID); - verify(taskRepository, never()).deleteById(any()); - assertEquals(TASK_NOT_FOUND, exception.getMessage()); - } - - @Test - void shouldCreateTask() { - Task task = getCreatedTask(); - TaskDTO taskDTO = getCreatedTaskDTO(); - TaskService service = getTaskService(); - when(mapper.toEntity(taskDTO)).thenReturn(task); - when(taskRepository.save(task)).thenReturn(task); - when(mapper.toDTO(task)).thenReturn(taskDTO); - TaskDTO result = service.createTask(taskDTO); - assertEquals(taskDTO, result); - verify(taskRepository, times(1)).save(task); - } - - @Test - void shouldUpdateTask() { - Task task = getCreatedTask(); - TaskService service = getTaskService(); - Task updatedTask = getUpdatedTask(); - TaskDTO updatedTaskDTO = getUpdatedTaskDTO(); - TaskStatusUpdateDTO taskStatusUpdateDTO = getTaskStatusUpdateDTO(); - when(taskRepository.findById(ID)).thenReturn(Optional.of(task)); - when(taskRepository.save(any(Task.class))).thenReturn(updatedTask); - when(mapper.toDTO(updatedTask)).thenReturn(updatedTaskDTO); - when(mapper.toStatusUpdateDTO(updatedTask)).thenReturn(taskStatusUpdateDTO); - TaskDTO result = service.updateTask(task.getId(), updatedTaskDTO); - assertEquals(updatedTaskDTO, result); - verify(taskRepository, times(1)).save(updatedTask); - verify(kafkaTaskProducer).sendTo(any(), eq(taskStatusUpdateDTO)); - } -} From 4c23c7d93973e04714dbedf6b9c908a66678e5f9 Mon Sep 17 00:00:00 2001 From: drewandrewd Date: Tue, 22 Apr 2025 22:34:11 +0500 Subject: [PATCH 3/3] Added test for controller, service and mapper --- .../controller/TaskControllerTest.java | 104 +++++++++++ .../integration/PostgresContainer.java | 21 +++ .../schoolproject/mapper/MainMapperTest.java | 47 +++++ .../service/TaskServiceTest.java | 162 ++++++++++++++++++ 4 files changed, 334 insertions(+) create mode 100644 src/test/java/com/example/schoolproject/controller/TaskControllerTest.java create mode 100644 src/test/java/com/example/schoolproject/integration/PostgresContainer.java create mode 100644 src/test/java/com/example/schoolproject/mapper/MainMapperTest.java create mode 100644 src/test/java/com/example/schoolproject/service/TaskServiceTest.java diff --git a/src/test/java/com/example/schoolproject/controller/TaskControllerTest.java b/src/test/java/com/example/schoolproject/controller/TaskControllerTest.java new file mode 100644 index 0000000..fddbe7b --- /dev/null +++ b/src/test/java/com/example/schoolproject/controller/TaskControllerTest.java @@ -0,0 +1,104 @@ +package com.example.schoolproject.controller; + +import com.example.schoolproject.dto.TaskDTO; +import com.example.schoolproject.entity.Task; +import com.example.schoolproject.entity.TaskStatus; +import com.example.schoolproject.integration.PostgresContainer; +import com.example.schoolproject.repository.TaskRepository; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.BeforeEach; +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.context.SpringBootTest; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.MockMvc; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; + +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@AutoConfigureMockMvc +public class TaskControllerTest extends PostgresContainer { + + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + @Autowired + private MockMvc mockMvc; + + @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private TaskRepository repository; + + private Long savedTaskId; + + @BeforeEach + void setUp() { + repository.deleteAll(); + Task saved = repository.save(getTask()); + savedTaskId = saved.getId(); + } + + private Task getTask() { + return new Task(null, "title", "description", 10L, TaskStatus.TODO); + } + + private TaskDTO getTaskDTO() { + return new TaskDTO("title", "description", 10L, TaskStatus.TODO); + } + + @Test + void shouldReturnAllTasks() throws Exception { + mockMvc.perform(get("/tasks")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$[0].title").value("title")) + .andExpect(jsonPath("$[0].description").value("description")) + .andExpect(jsonPath("$[0].userId").value(10L)); + } + + @Test + void shouldReturnTaskById() throws Exception { + mockMvc.perform(get("/tasks/" + savedTaskId)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("title")) + .andExpect(jsonPath("$.description").value("description")) + .andExpect(jsonPath("$.userId").value(10L)); + } + + @Test + void shouldCreateTask() throws Exception { + mockMvc.perform(post("/tasks") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(getTaskDTO()))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("title")) + .andExpect(jsonPath("$.description").value("description")) + .andExpect(jsonPath("$.userId").value(10L)); + } + + @Test + void shouldUpdateTask() throws Exception { + mockMvc.perform(put("/tasks/" + savedTaskId) + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(getTaskDTO()))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.title").value("title")) + .andExpect(jsonPath("$.description").value("description")) + .andExpect(jsonPath("$.userId").value(10L)); + } + + @Test + void shouldDeleteTask() throws Exception { + mockMvc.perform(delete("/tasks/" + savedTaskId)) + .andExpect(status().isNoContent()); + } + + @Test + void shouldReturnNotFoundWhenTaskDoesNotExist() throws Exception { + mockMvc.perform(get("/tasks/99999")) + .andExpect(status().isNotFound()) + .andExpect(content().string("Task with id 99999 is not found")); + } +} diff --git a/src/test/java/com/example/schoolproject/integration/PostgresContainer.java b/src/test/java/com/example/schoolproject/integration/PostgresContainer.java new file mode 100644 index 0000000..8b38a1f --- /dev/null +++ b/src/test/java/com/example/schoolproject/integration/PostgresContainer.java @@ -0,0 +1,21 @@ +package com.example.schoolproject.integration; + +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +@Testcontainers +public class PostgresContainer { + + @Container + public static PostgreSQLContainer postgres = new PostgreSQLContainer<>("postgres:16"); + + @DynamicPropertySource + public static void properties(DynamicPropertyRegistry registry) { + registry.add("spring.datasource.url", postgres::getJdbcUrl); + registry.add("spring.datasource.username", postgres::getUsername); + registry.add("spring.datasource.password", postgres::getPassword); + } +} diff --git a/src/test/java/com/example/schoolproject/mapper/MainMapperTest.java b/src/test/java/com/example/schoolproject/mapper/MainMapperTest.java new file mode 100644 index 0000000..a77e219 --- /dev/null +++ b/src/test/java/com/example/schoolproject/mapper/MainMapperTest.java @@ -0,0 +1,47 @@ +package com.example.schoolproject.mapper; + +import com.example.schoolproject.dto.TaskDTO; +import com.example.schoolproject.dto.TaskStatusUpdateDTO; +import com.example.schoolproject.entity.Task; +import com.example.schoolproject.entity.TaskStatus; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mapstruct.factory.Mappers; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +public class MainMapperTest { + + private MainMapper mapper = Mappers.getMapper(MainMapper.class); + + private Task getCreatedTask() { + return new Task(1L, "title", "description", 10L, TaskStatus.TODO); + } + + private TaskDTO getCreatedTaskDTO() { + return new TaskDTO("title", "description", 10L, TaskStatus.TODO); + } + + private TaskStatusUpdateDTO getTaskStatusUpdateDTO() { + return new TaskStatusUpdateDTO(1L, TaskStatus.TODO); + } + + @Test + void shouldReturnTaskDTO() { + TaskDTO result = mapper.toDTO(getCreatedTask()); + Assertions.assertEquals(result, getCreatedTaskDTO()); + } + + @Test + void shouldReturnTaskEntity() { + Task result = mapper.toEntity(getCreatedTaskDTO()); + Assertions.assertEquals(result, getCreatedTask()); + } + + @Test + void shouldReturnTaskStatusUpdateDTO() { + TaskStatusUpdateDTO result = mapper.toStatusUpdateDTO(getCreatedTask()); + Assertions.assertEquals(result, getTaskStatusUpdateDTO()); + } +} diff --git a/src/test/java/com/example/schoolproject/service/TaskServiceTest.java b/src/test/java/com/example/schoolproject/service/TaskServiceTest.java new file mode 100644 index 0000000..9d46905 --- /dev/null +++ b/src/test/java/com/example/schoolproject/service/TaskServiceTest.java @@ -0,0 +1,162 @@ +package com.example.schoolproject.service; + +import com.example.schoolproject.dto.TaskDTO; +import com.example.schoolproject.dto.TaskStatusUpdateDTO; +import com.example.schoolproject.entity.Task; +import com.example.schoolproject.entity.TaskStatus; +import com.example.schoolproject.exception.TaskNotFoundException; +import com.example.schoolproject.kafka.KafkaTaskProducer; +import com.example.schoolproject.mapper.MainMapper; +import com.example.schoolproject.repository.TaskRepository; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +public class TaskServiceTest { + + @Mock + private TaskRepository taskRepository; + + @Mock + private KafkaTaskProducer kafkaTaskProducer; + + @Mock + private MainMapper mapper; + + private static final Long ID = 1L; + private static final String TASKS_NOT_FOUND = "Tasks are not found"; + private static final String TASK_NOT_FOUND = "Task with id " + ID + " is not found"; + + @BeforeEach + void setUp() { + } + + private Task getCreatedTask() { + return new Task(ID, "title", "description", 10L, TaskStatus.TODO); + } + + private TaskDTO getCreatedTaskDTO() { + return new TaskDTO("title", "description", 10L, TaskStatus.TODO); + } + + private Task getUpdatedTask() { + return new Task(ID, "newTitle", "newDescription", 11L, TaskStatus.DONE); + } + + private TaskDTO getUpdatedTaskDTO() { + return new TaskDTO("newTitle", "newDescription", 11L, TaskStatus.DONE); + } + + private TaskStatusUpdateDTO getTaskStatusUpdateDTO() { + return new TaskStatusUpdateDTO(ID, TaskStatus.DONE); + } + + private TaskService getTaskService() { + return new TaskServiceImpl(taskRepository, mapper, kafkaTaskProducer); + } + + @Test + void shouldReturnTaskByIdWhenExist() { + Task task = getCreatedTask(); + TaskDTO taskDTO = getCreatedTaskDTO(); + TaskService service = getTaskService(); + when(taskRepository.findById(ID)).thenReturn(Optional.of(task)); + when(mapper.toDTO(task)).thenReturn(taskDTO); + TaskDTO result = service.getTaskById(ID); + Assertions.assertNotNull(result); + assertEquals(taskDTO, result); + verify(taskRepository, times(1)).findById(ID); + } + + @Test + void shouldTrowExceptionWhenTaskNotFoundById() { + TaskService service = getTaskService(); + when(taskRepository.findById(ID)).thenReturn(Optional.empty()); + TaskNotFoundException exception = Assertions.assertThrows(TaskNotFoundException.class, () -> service.getTaskById(ID)); + verify(taskRepository).findById(any()); + assertEquals(TASK_NOT_FOUND, exception.getMessage()); + } + + @Test + void shouldReturnAllTasksWhenExist() { + Task task = getCreatedTask(); + TaskDTO taskDTO = getCreatedTaskDTO(); + TaskService service = getTaskService(); + when(taskRepository.findAll()).thenReturn(List.of(task)); + when(mapper.toDTO(task)).thenReturn(taskDTO); + List result = service.getAllTasks(); + Assertions.assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(taskDTO, result.get(0)); + verify(taskRepository, times(1)).findAll(); + } + + @Test + void shouldThrowExceptionWhenTasksNotFound() { + TaskService service = getTaskService(); + when(taskRepository.findAll()).thenReturn(Collections.emptyList()); + TaskNotFoundException exception = Assertions.assertThrows(TaskNotFoundException.class, () -> service.getAllTasks()); + verify(taskRepository).findAll(); + assertEquals(TASKS_NOT_FOUND, exception.getMessage()); + } + + @Test + void shouldDeleteTaskWhenExist() { + TaskService service = getTaskService(); + when(taskRepository.existsById(ID)).thenReturn(true); + service.deleteTask(ID); + verify(taskRepository, times(1)).existsById(ID); + verify(taskRepository, times(1)).deleteById(ID); + } + + @Test + void shouldThrowExceptionInsteadDeleting() { + TaskService service = getTaskService(); + when(taskRepository.existsById(ID)).thenReturn(false); + TaskNotFoundException exception = Assertions.assertThrows(TaskNotFoundException.class, () -> service.deleteTask(ID)); + verify(taskRepository).existsById(ID); + verify(taskRepository, never()).deleteById(any()); + assertEquals(TASK_NOT_FOUND, exception.getMessage()); + } + + @Test + void shouldCreateTask() { + Task task = getCreatedTask(); + TaskDTO taskDTO = getCreatedTaskDTO(); + TaskService service = getTaskService(); + when(mapper.toEntity(taskDTO)).thenReturn(task); + when(taskRepository.save(task)).thenReturn(task); + when(mapper.toDTO(task)).thenReturn(taskDTO); + TaskDTO result = service.createTask(taskDTO); + assertEquals(taskDTO, result); + verify(taskRepository, times(1)).save(task); + } + + @Test + void shouldUpdateTask() { + Task task = getCreatedTask(); + TaskService service = getTaskService(); + Task updatedTask = getUpdatedTask(); + TaskDTO updatedTaskDTO = getUpdatedTaskDTO(); + TaskStatusUpdateDTO taskStatusUpdateDTO = getTaskStatusUpdateDTO(); + when(taskRepository.findById(ID)).thenReturn(Optional.of(task)); + when(taskRepository.save(any(Task.class))).thenReturn(updatedTask); + when(mapper.toDTO(updatedTask)).thenReturn(updatedTaskDTO); + when(mapper.toStatusUpdateDTO(updatedTask)).thenReturn(taskStatusUpdateDTO); + TaskDTO result = service.updateTask(task.getId(), updatedTaskDTO); + assertEquals(updatedTaskDTO, result); + verify(taskRepository, times(1)).save(updatedTask); + verify(kafkaTaskProducer).sendTo(any(), eq(taskStatusUpdateDTO)); + } +}