Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

не нужно шарить между тестами, тестовые данные


@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"));
}
}
Original file line number Diff line number Diff line change
@@ -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");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

это можно было сделать 1 строкой в yml


@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);
}
}
47 changes: 47 additions & 0 deletions src/test/java/com/example/schoolproject/mapper/MainMapperTest.java
Original file line number Diff line number Diff line change
@@ -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());
}
}
162 changes: 162 additions & 0 deletions src/test/java/com/example/schoolproject/service/TaskServiceTest.java
Original file line number Diff line number Diff line change
@@ -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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

если это мок, то что тестировать? итоговый результат уже заготовлен?…


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<TaskDTO> 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));
}
}