diff --git a/pom.xml b/pom.xml
index 6af527b..59b80c5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -188,6 +188,8 @@
**/service/*.class
**/service/**/*.class
+ **/controller/*.class
+ **/controller/**/*.class
diff --git a/src/test/java/br/com/springnoobs/reminderapi/reminder/controller/ReminderControllerTest.java b/src/test/java/br/com/springnoobs/reminderapi/reminder/controller/ReminderControllerTest.java
new file mode 100644
index 0000000..36108df
--- /dev/null
+++ b/src/test/java/br/com/springnoobs/reminderapi/reminder/controller/ReminderControllerTest.java
@@ -0,0 +1,179 @@
+package br.com.springnoobs.reminderapi.reminder.controller;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import br.com.springnoobs.reminderapi.reminder.dto.request.CreateReminderRequestDTO;
+import br.com.springnoobs.reminderapi.reminder.dto.request.UpdateReminderRequestDTO;
+import br.com.springnoobs.reminderapi.reminder.dto.response.ReminderResponseDTO;
+import br.com.springnoobs.reminderapi.reminder.exception.NotFoundException;
+import br.com.springnoobs.reminderapi.reminder.exception.PastRemindAtException;
+import br.com.springnoobs.reminderapi.reminder.service.ReminderService;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.time.Instant;
+import java.util.List;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.bean.override.mockito.MockitoBean;
+import org.springframework.test.web.servlet.MockMvc;
+
+@WebMvcTest(ReminderController.class)
+@ActiveProfiles("test")
+class ReminderControllerTest {
+
+ @Autowired
+ private MockMvc mockMvc;
+
+ @Autowired
+ private ObjectMapper objectMapper;
+
+ @MockitoBean
+ private ReminderService service;
+
+ @Test
+ void shouldReturnReminderListWhenListAllReminders() throws Exception {
+ ReminderResponseDTO response1 = new ReminderResponseDTO("Lembrete A", Instant.now());
+ ReminderResponseDTO response2 = new ReminderResponseDTO("Lembrete B", Instant.now());
+
+ Page pageResult = new PageImpl<>(List.of(response1, response2));
+
+ when(service.findAll(any())).thenReturn(pageResult);
+
+ mockMvc.perform(get("/reminders?page=0&size=10").accept(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.content[0].title").value("Lembrete A"))
+ .andExpect(jsonPath("$.content[1].title").value("Lembrete B"))
+ .andExpect(jsonPath("$.page.totalElements").value(2));
+ }
+
+ @Test
+ public void shouldReturnEmptyReminderListWhenListAllReminders() throws Exception {
+ when(service.findAll(any())).thenReturn(Page.empty());
+
+ mockMvc.perform(get("/reminders?page=0&size=10").accept(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.content").isEmpty());
+ }
+
+ @Test
+ void shouldReturnReminderWhenFindByIdWithValidId() throws Exception {
+ long reminderId = 1L;
+ var response = new ReminderResponseDTO("Test Reminder", Instant.now());
+ when(service.findById(reminderId)).thenReturn(response);
+
+ mockMvc.perform(get("/reminders/{id}", reminderId).accept(MediaType.APPLICATION_JSON))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.title").value("Test Reminder"));
+ }
+
+ @Test
+ void shouldReturnNotFoundWhenFindByIdWithInvalidId() throws Exception {
+ long reminderId = 99L;
+ when(service.findById(reminderId)).thenThrow(new NotFoundException("Reminder not found"));
+
+ mockMvc.perform(get("/reminders/{id}", reminderId).accept(MediaType.APPLICATION_JSON))
+ .andExpect(status().isNotFound());
+ }
+
+ @Test
+ void shouldCreateReminderWhenRequestIsValid() throws Exception {
+ var request = new CreateReminderRequestDTO("New Reminder", Instant.now().plusSeconds(60));
+ var response = new ReminderResponseDTO("New Reminder", request.remindAt());
+
+ when(service.create(any(CreateReminderRequestDTO.class))).thenReturn(response);
+
+ mockMvc.perform(post("/reminders")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(request)))
+ .andExpect(status().isCreated())
+ .andExpect(jsonPath("$.title").value("New Reminder"));
+ }
+
+ @Test
+ void shouldReturnBadRequestWhenCreatingReminderWithPastDate() throws Exception {
+ var request =
+ new CreateReminderRequestDTO("Past Reminder", Instant.now().minusSeconds(60));
+
+ when(service.create(any(CreateReminderRequestDTO.class)))
+ .thenThrow(new PastRemindAtException("Remind at date must be in the future"));
+
+ mockMvc.perform(post("/reminders")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(request)))
+ .andExpect(status().isBadRequest());
+ }
+
+ @Test
+ void shouldUpdateReminderWhenRequestIsValid() throws Exception {
+ long reminderId = 1L;
+ var request =
+ new UpdateReminderRequestDTO("Updated Reminder", Instant.now().plusSeconds(60));
+ var response = new ReminderResponseDTO("Updated Reminder", request.remindAt());
+
+ when(service.update(any(Long.class), any(UpdateReminderRequestDTO.class)))
+ .thenReturn(response);
+
+ mockMvc.perform(put("/reminders/{id}", reminderId)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(request)))
+ .andExpect(status().isOk())
+ .andExpect(jsonPath("$.title").value("Updated Reminder"));
+ }
+
+ @Test
+ void shouldReturnBadRequestWhenUpdatingReminderWithPastDate() throws Exception {
+ long reminderId = 1L;
+ var request =
+ new UpdateReminderRequestDTO("Past Reminder", Instant.now().minusSeconds(60));
+
+ when(service.update(any(Long.class), any(UpdateReminderRequestDTO.class)))
+ .thenThrow(new PastRemindAtException("Remind at date must be in the future"));
+
+ mockMvc.perform(put("/reminders/{id}", reminderId)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(request)))
+ .andExpect(status().isBadRequest());
+ }
+
+ @Test
+ void shouldReturnNotFoundWhenUpdatingNonExistentReminder() throws Exception {
+ long reminderId = 99L;
+ var request =
+ new UpdateReminderRequestDTO("Updated Reminder", Instant.now().plusSeconds(60));
+
+ when(service.update(any(Long.class), any(UpdateReminderRequestDTO.class)))
+ .thenThrow(new NotFoundException("Reminder not found"));
+
+ mockMvc.perform(put("/reminders/{id}", reminderId)
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(objectMapper.writeValueAsString(request)))
+ .andExpect(status().isNotFound());
+ }
+
+ @Test
+ void shouldDeleteReminderWhenIdIsValid() throws Exception {
+ long reminderId = 1L;
+
+ mockMvc.perform(delete("/reminders/{id}", reminderId)).andExpect(status().isNoContent());
+ }
+
+ @Test
+ void shouldReturnNotFoundWhenDeletingNonExistentReminder() throws Exception {
+ long reminderId = 99L;
+ doThrow(new NotFoundException("Reminder not found")).when(service).delete(reminderId);
+
+ mockMvc.perform(delete("/reminders/{id}", reminderId)).andExpect(status().isNotFound());
+ }
+}