From d42acd748f6798633e6c8343eb33c64f982c8c08 Mon Sep 17 00:00:00 2001 From: "fernanda.mello" Date: Sat, 6 Sep 2025 14:18:44 -0300 Subject: [PATCH 1/3] feat: Cria endpoints de busca de UFs e municipios --- .../src/application/clients/IbgeClient.java | 73 +++++++++++++++++++ .../controllers/LocationController.java | 39 ++++++++++ .../src/application/dto/CityResponseDTO.java | 19 +++++ .../src/application/dto/LocationDataDTO.java | 15 ++++ .../application/dto/LocationResponseDTO.java | 19 +++++ .../src/application/dto/StateResponseDTO.java | 22 ++++++ .../application/services/LocationService.java | 22 ++++++ .../src/core/domain/entities/User.java | 2 +- .../exceptions/ClientTimeoutException.java | 7 ++ .../configs/GlobalExceptionHandler.java | 29 +++++--- .../infrastructure/configs/OpenApiConfig.java | 13 +++- .../configs/RestTemplateConfig.java | 27 +++++++ .../src/main/resources/application.properties | 4 + .../dto/RefreshTokenRequestDTOTest.java | 9 ++- .../dto/RefreshTokenResponseDTOTest.java | 8 +- .../configs}/JwtAuthenticationFilterTest.java | 17 +++-- .../configs}/JwtRefreshTokenTest.java | 8 +- .../configs}/JwtServiceTest.java | 18 +++-- .../configs}/SecurityConfigurationTest.java | 19 ++--- 19 files changed, 320 insertions(+), 50 deletions(-) create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/application/clients/IbgeClient.java create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/LocationController.java create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityResponseDTO.java create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationDataDTO.java create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationResponseDTO.java create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateResponseDTO.java create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/application/services/LocationService.java create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/exceptions/ClientTimeoutException.java create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/RestTemplateConfig.java rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/application}/dto/RefreshTokenRequestDTOTest.java (88%) rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/application}/dto/RefreshTokenResponseDTOTest.java (97%) rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/infrastructure/configs}/JwtAuthenticationFilterTest.java (93%) rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/infrastructure/configs}/JwtRefreshTokenTest.java (92%) rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/infrastructure/configs}/JwtServiceTest.java (92%) rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/infrastructure/configs}/SecurityConfigurationTest.java (95%) diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/clients/IbgeClient.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/clients/IbgeClient.java new file mode 100644 index 00000000..d4d2350a --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/clients/IbgeClient.java @@ -0,0 +1,73 @@ +package com.pointtils.pointtils.src.application.clients; + +import com.pointtils.pointtils.src.application.dto.CityResponseDTO; +import com.pointtils.pointtils.src.application.dto.LocationDataDTO; +import com.pointtils.pointtils.src.application.dto.StateResponseDTO; +import com.pointtils.pointtils.src.core.domain.exceptions.ClientTimeoutException; +import jakarta.persistence.EntityNotFoundException; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.ArrayUtils; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.List; +import java.util.function.Function; + +@Slf4j +@Component +public class IbgeClient { + + private final RestTemplate restTemplate; + private final String stateUrl; + private final String cityUrl; + + public IbgeClient(@Qualifier("ibgeRestTemplate") RestTemplate restTemplate, + @Value("${client.ibge.state-url}") String stateUrl, + @Value("${client.ibge.city-url}") String cityUrl) { + this.restTemplate = restTemplate; + this.stateUrl = stateUrl; + this.cityUrl = cityUrl; + } + + public List getStateList() { + try { + log.info("Iniciando uma requisicao para a API do IBGE para buscar a lista de UFs"); + ResponseEntity stateResponse = restTemplate.getForEntity(stateUrl, StateResponseDTO[].class); + Function mapper = state -> new LocationDataDTO(state.getAbbreviation()); + return formatResponseData(stateResponse.getBody(), mapper, "UFs não encontradas"); + } catch (ResourceAccessException ex) { + log.error("Timeout na requisicao para a API do IBGE para buscar a lista de UFs", ex); + throw new ClientTimeoutException("Timeout ao acessar o serviço de UFs"); + } + } + + public List getCityListByState(String state) { + try { + log.info("Iniciando uma requisicao para a API do IBGE para buscar a lista de municípios da UF {}", state); + ResponseEntity cityResponse = restTemplate.getForEntity(cityUrl, CityResponseDTO[].class, state); + Function mapper = city -> new LocationDataDTO(city.getName()); + return formatResponseData(cityResponse.getBody(), mapper, "Municípios não encontrados"); + } catch (ResourceAccessException ex) { + log.error("Timeout na requisicao para a API do IBGE para buscar a lista de municípios da UF {}", state, ex); + throw new ClientTimeoutException("Timeout ao acessar o serviço de municípios"); + } + } + + private List formatResponseData(T[] responseBody, + Function mapper, + String errorMessage) { + if (ArrayUtils.isEmpty(responseBody)) { + throw new EntityNotFoundException(errorMessage); + } + return Arrays.stream(responseBody) + .map(mapper) + .sorted(Comparator.comparing(LocationDataDTO::getName)) + .toList(); + } +} diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/LocationController.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/LocationController.java new file mode 100644 index 00000000..9d010bdd --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/LocationController.java @@ -0,0 +1,39 @@ +package com.pointtils.pointtils.src.application.controllers; + +import com.pointtils.pointtils.src.application.dto.LocationResponseDTO; +import com.pointtils.pointtils.src.application.services.LocationService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/v1/location") +@Tag(name = "Location Controller", description = "Endpoints para gerenciar dados de localização") +public class LocationController { + + private final LocationService locationService; + + @GetMapping("/states") + @ResponseStatus(HttpStatus.OK) + @SecurityRequirement(name = "bearerAuth") + @Operation(summary = "Busca todas as UFs brasileiras") + public LocationResponseDTO getStates() { + return locationService.getAllStates(); + } + + @GetMapping("/states/{stateId}/cities") + @ResponseStatus(HttpStatus.OK) + @SecurityRequirement(name = "bearerAuth") + @Operation(summary = "Busca todos os municípios de uma determinada UF brasileira") + public LocationResponseDTO getCitiesByState(@PathVariable String stateId) { + return locationService.getCitiesByState(stateId); + } +} diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityResponseDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityResponseDTO.java new file mode 100644 index 00000000..a6f71b76 --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityResponseDTO.java @@ -0,0 +1,19 @@ +package com.pointtils.pointtils.src.application.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class CityResponseDTO { + + private Long id; + + @JsonProperty("nome") + private String name; +} diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationDataDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationDataDTO.java new file mode 100644 index 00000000..ac7c1880 --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationDataDTO.java @@ -0,0 +1,15 @@ +package com.pointtils.pointtils.src.application.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class LocationDataDTO { + + private String name; +} diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationResponseDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationResponseDTO.java new file mode 100644 index 00000000..6fd7477a --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationResponseDTO.java @@ -0,0 +1,19 @@ +package com.pointtils.pointtils.src.application.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class LocationResponseDTO { + + private boolean success; + private String message; + private List data; +} diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateResponseDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateResponseDTO.java new file mode 100644 index 00000000..4195ea0b --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateResponseDTO.java @@ -0,0 +1,22 @@ +package com.pointtils.pointtils.src.application.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class StateResponseDTO { + + private Long id; + + @JsonProperty("sigla") + private String abbreviation; + + @JsonProperty("nome") + private String name; +} diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/LocationService.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/LocationService.java new file mode 100644 index 00000000..c0fd83ed --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/LocationService.java @@ -0,0 +1,22 @@ +package com.pointtils.pointtils.src.application.services; + +import com.pointtils.pointtils.src.application.clients.IbgeClient; +import com.pointtils.pointtils.src.application.dto.LocationResponseDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class LocationService { + + private final IbgeClient ibgeClient; + + public LocationResponseDTO getAllStates() { + return new LocationResponseDTO(true, "UFs encontradas com sucesso", ibgeClient.getStateList()); + } + + public LocationResponseDTO getCitiesByState(String state) { + return new LocationResponseDTO(true, "Municípios encontrados com sucesso", + ibgeClient.getCityListByState(state)); + } +} diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/entities/User.java b/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/entities/User.java index f798a673..c873abdd 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/entities/User.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/entities/User.java @@ -11,7 +11,7 @@ @Entity @Inheritance(strategy = InheritanceType.JOINED) -@Table(name = "user_tab") +@Table(name = "users") public abstract class User { @Id diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/exceptions/ClientTimeoutException.java b/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/exceptions/ClientTimeoutException.java new file mode 100644 index 00000000..a0a61061 --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/exceptions/ClientTimeoutException.java @@ -0,0 +1,7 @@ +package com.pointtils.pointtils.src.core.domain.exceptions; + +public class ClientTimeoutException extends RuntimeException { + public ClientTimeoutException(String message) { + super(message); + } +} \ No newline at end of file diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/GlobalExceptionHandler.java b/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/GlobalExceptionHandler.java index f0b83d10..39f577a2 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/GlobalExceptionHandler.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/GlobalExceptionHandler.java @@ -1,42 +1,41 @@ package com.pointtils.pointtils.src.infrastructure.configs; +import com.pointtils.pointtils.src.core.domain.exceptions.AuthenticationException; +import com.pointtils.pointtils.src.core.domain.exceptions.ClientTimeoutException; +import jakarta.persistence.EntityNotFoundException; +import lombok.AllArgsConstructor; +import lombok.Data; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.context.request.WebRequest; -import com.pointtils.pointtils.src.core.domain.exceptions.AuthenticationException; - -import jakarta.persistence.EntityNotFoundException; -import lombok.AllArgsConstructor; -import lombok.Data; - @ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(EntityNotFoundException.class) public ResponseEntity handleEntityNotFoundException( EntityNotFoundException ex, WebRequest request) { - + ErrorResponse errorResponse = new ErrorResponse( HttpStatus.NOT_FOUND.value(), ex.getMessage(), System.currentTimeMillis()); - + return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND); } @ExceptionHandler(Exception.class) public ResponseEntity handleGlobalException( Exception ex, WebRequest request) { - + ErrorResponse errorResponse = new ErrorResponse( HttpStatus.INTERNAL_SERVER_ERROR.value(), "An unexpected error occurred", System.currentTimeMillis()); - + return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); } @@ -107,6 +106,16 @@ public ResponseEntity handleAuthentication(AuthenticationExceptio return new ResponseEntity<>(errorResponse, HttpStatus.INTERNAL_SERVER_ERROR); } + @ExceptionHandler(ClientTimeoutException.class) + public ResponseEntity handleClientTimeoutException(ClientTimeoutException ex) { + ErrorResponse errorResponse = new ErrorResponse( + HttpStatus.GATEWAY_TIMEOUT.value(), + ex.getMessage(), + System.currentTimeMillis()); + + return new ResponseEntity<>(errorResponse, HttpStatus.GATEWAY_TIMEOUT); + } + @Data @AllArgsConstructor public static class ErrorResponse { diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/OpenApiConfig.java b/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/OpenApiConfig.java index f6bb466d..de317e9c 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/OpenApiConfig.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/OpenApiConfig.java @@ -1,13 +1,20 @@ package com.pointtils.pointtils.src.infrastructure.configs; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - +import io.swagger.v3.oas.annotations.enums.SecuritySchemeType; +import io.swagger.v3.oas.annotations.security.SecurityScheme; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Contact; import io.swagger.v3.oas.models.info.Info; import io.swagger.v3.oas.models.info.License; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +@SecurityScheme( + name = "bearerAuth", + type = SecuritySchemeType.HTTP, + bearerFormat = "JWT", + scheme = "bearer" +) @Configuration public class OpenApiConfig { diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/RestTemplateConfig.java b/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/RestTemplateConfig.java new file mode 100644 index 00000000..dd1bb0d6 --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/infrastructure/configs/RestTemplateConfig.java @@ -0,0 +1,27 @@ +package com.pointtils.pointtils.src.infrastructure.configs; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestFactory; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.web.client.RestTemplate; + +@Configuration +public class RestTemplateConfig { + + @Value("${client.ibge.timeout:3000}") + private Integer ibgeTimeoutInMs; + + @Bean + public RestTemplate ibgeRestTemplate() { + return new RestTemplate(buildClientHttpRequestFactory(ibgeTimeoutInMs)); + } + + private ClientHttpRequestFactory buildClientHttpRequestFactory(Integer timeoutInMs) { + SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory(); + factory.setConnectTimeout(timeoutInMs); + factory.setReadTimeout(timeoutInMs); + return factory; + } +} diff --git a/pointtils/src/main/resources/application.properties b/pointtils/src/main/resources/application.properties index 22e192f7..293a1536 100644 --- a/pointtils/src/main/resources/application.properties +++ b/pointtils/src/main/resources/application.properties @@ -23,3 +23,7 @@ spring.flyway.validate-on-migrate=${SPRING_FLYWAY_VALIDATE_ON_MIGRATE} springdoc.api-docs.enabled=${SPRINGDOC_API_DOCS_ENABLED} springdoc.swagger-ui.enabled=${SPRINGDOC_SWAGGER_UI_ENABLED} springdoc.swagger-ui.path=${SPRINGDOC_SWAGGER_UI_PATH} + +# Clientes HTTP +client.ibge.state-url=https://servicodados.ibge.gov.br/api/v1/localidades/estados +client.ibge.city-url=https://servicodados.ibge.gov.br/api/v1/localidades/estados/{state}/municipios \ No newline at end of file diff --git a/pointtils/src/test/java/com/pointtils/pointtils/dto/RefreshTokenRequestDTOTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/RefreshTokenRequestDTOTest.java similarity index 88% rename from pointtils/src/test/java/com/pointtils/pointtils/dto/RefreshTokenRequestDTOTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/RefreshTokenRequestDTOTest.java index db504835..6336f507 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/dto/RefreshTokenRequestDTOTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/RefreshTokenRequestDTOTest.java @@ -1,9 +1,12 @@ -package com.pointtils.pointtils.dto; +package com.pointtils.pointtils.src.application.dto; -import com.pointtils.pointtils.src.application.dto.RefreshTokenRequestDTO; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; class RefreshTokenRequestDTOTest { diff --git a/pointtils/src/test/java/com/pointtils/pointtils/dto/RefreshTokenResponseDTOTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/RefreshTokenResponseDTOTest.java similarity index 97% rename from pointtils/src/test/java/com/pointtils/pointtils/dto/RefreshTokenResponseDTOTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/RefreshTokenResponseDTOTest.java index 202c183b..83dcf4bf 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/dto/RefreshTokenResponseDTOTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/RefreshTokenResponseDTOTest.java @@ -1,14 +1,12 @@ -package com.pointtils.pointtils.dto; +package com.pointtils.pointtils.src.application.dto; + +import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; - -import com.pointtils.pointtils.src.application.dto.RefreshTokenResponseDTO; -import com.pointtils.pointtils.src.application.dto.TokensDTO; class RefreshTokenResponseDTOTest { diff --git a/pointtils/src/test/java/com/pointtils/pointtils/JwtAuthenticationFilterTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/JwtAuthenticationFilterTest.java similarity index 93% rename from pointtils/src/test/java/com/pointtils/pointtils/JwtAuthenticationFilterTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/JwtAuthenticationFilterTest.java index 0558c439..048b35ba 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/JwtAuthenticationFilterTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/JwtAuthenticationFilterTest.java @@ -1,9 +1,6 @@ -package com.pointtils.pointtils; +package com.pointtils.pointtils.src.infrastructure.configs; -import com.pointtils.pointtils.src.infrastructure.configs.JwtAuthenticationFilter; -import com.pointtils.pointtils.src.infrastructure.configs.JwtService; import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.junit.jupiter.api.BeforeEach; @@ -14,16 +11,20 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.test.util.ReflectionTestUtils; -import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.Method; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class JwtAuthenticationFilterTest { diff --git a/pointtils/src/test/java/com/pointtils/pointtils/JwtRefreshTokenTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/JwtRefreshTokenTest.java similarity index 92% rename from pointtils/src/test/java/com/pointtils/pointtils/JwtRefreshTokenTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/JwtRefreshTokenTest.java index 6da907a8..085ad082 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/JwtRefreshTokenTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/JwtRefreshTokenTest.java @@ -1,14 +1,12 @@ -package com.pointtils.pointtils; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; +package com.pointtils.pointtils.src.infrastructure.configs; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.TestPropertySource; -import com.pointtils.pointtils.src.infrastructure.configs.JwtService; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; @SpringBootTest @TestPropertySource(locations = "classpath:application.properties") diff --git a/pointtils/src/test/java/com/pointtils/pointtils/JwtServiceTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/JwtServiceTest.java similarity index 92% rename from pointtils/src/test/java/com/pointtils/pointtils/JwtServiceTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/JwtServiceTest.java index 8184c841..666ddf38 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/JwtServiceTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/JwtServiceTest.java @@ -1,4 +1,4 @@ -package com.pointtils.pointtils; +package com.pointtils.pointtils.src.infrastructure.configs; import io.jsonwebtoken.Claims; import io.jsonwebtoken.ExpiredJwtException; @@ -7,11 +7,17 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.springframework.test.util.ReflectionTestUtils; -import com.pointtils.pointtils.src.infrastructure.configs.JwtService; import java.util.Date; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; class JwtServiceTest { private JwtService jwtService; @@ -84,7 +90,7 @@ void shouldExtractIssuedAtFromToken() { // Then assertNotNull(issuedAt); long issuedAtTime = issuedAt.getTime(); - assertTrue(issuedAtTime >= beforeTokenGeneration, + assertTrue(issuedAtTime >= beforeTokenGeneration, "IssuedAt time " + issuedAtTime + " should be >= " + beforeTokenGeneration); assertTrue(issuedAtTime <= afterTokenGeneration, "IssuedAt time " + issuedAtTime + " should be <= " + afterTokenGeneration); @@ -140,7 +146,7 @@ void shouldDetectExpiredToken() { JwtService expiredJwtService = new JwtService(); ReflectionTestUtils.setField(expiredJwtService, "secretKey", TEST_SECRET_KEY); ReflectionTestUtils.setField(expiredJwtService, "jwtExpiration", -60000L); // Already expired (negative 1 minute) - + String expiredToken = expiredJwtService.generateToken("testuser"); // When & Then - Expect an ExpiredJwtException to be thrown when checking expired token @@ -166,7 +172,7 @@ void shouldThrowExceptionForTokenWithWrongSignature() { JwtService differentKeyService = new JwtService(); ReflectionTestUtils.setField(differentKeyService, "secretKey", "ZGlmZmVyZW50a2V5ZGlmZmVyZW50a2V5ZGlmZmVyZW50a2V5ZGlmZmVyZW50a2V5"); ReflectionTestUtils.setField(differentKeyService, "jwtExpiration", JWT_EXPIRATION); - + String tokenWithDifferentKey = differentKeyService.generateToken("testuser"); // When & Then diff --git a/pointtils/src/test/java/com/pointtils/pointtils/SecurityConfigurationTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/SecurityConfigurationTest.java similarity index 95% rename from pointtils/src/test/java/com/pointtils/pointtils/SecurityConfigurationTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/SecurityConfigurationTest.java index 6eb817f2..0bf70506 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/SecurityConfigurationTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/infrastructure/configs/SecurityConfigurationTest.java @@ -1,7 +1,5 @@ -package com.pointtils.pointtils; +package com.pointtils.pointtils.src.infrastructure.configs; -import com.pointtils.pointtils.src.infrastructure.configs.JwtAuthenticationFilter; -import com.pointtils.pointtils.src.infrastructure.configs.SecurityConfiguration; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; @@ -11,7 +9,10 @@ import java.lang.reflect.Method; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; @ExtendWith(MockitoExtension.class) class SecurityConfigurationTest { @@ -42,7 +43,7 @@ void corsConfigurationShouldAllowAllOrigins() throws Exception { Method corsConfigurationSourceMethod = SecurityConfiguration.class.getDeclaredMethod("corsConfigurationSource"); corsConfigurationSourceMethod.setAccessible(true); CorsConfigurationSource corsConfigurationSource = (CorsConfigurationSource) corsConfigurationSourceMethod.invoke(securityConfiguration); - + MockHttpServletRequest request = new MockHttpServletRequest(); var corsConfiguration = corsConfigurationSource.getCorsConfiguration(request); @@ -61,7 +62,7 @@ void corsConfigurationShouldAllowExpectedMethods() throws Exception { Method corsConfigurationSourceMethod = SecurityConfiguration.class.getDeclaredMethod("corsConfigurationSource"); corsConfigurationSourceMethod.setAccessible(true); CorsConfigurationSource corsConfigurationSource = (CorsConfigurationSource) corsConfigurationSourceMethod.invoke(securityConfiguration); - + MockHttpServletRequest request = new MockHttpServletRequest(); var corsConfiguration = corsConfigurationSource.getCorsConfiguration(request); @@ -84,7 +85,7 @@ void corsConfigurationShouldAllowExpectedHeaders() throws Exception { Method corsConfigurationSourceMethod = SecurityConfiguration.class.getDeclaredMethod("corsConfigurationSource"); corsConfigurationSourceMethod.setAccessible(true); CorsConfigurationSource corsConfigurationSource = (CorsConfigurationSource) corsConfigurationSourceMethod.invoke(securityConfiguration); - + MockHttpServletRequest request = new MockHttpServletRequest(); var corsConfiguration = corsConfigurationSource.getCorsConfiguration(request); @@ -107,7 +108,7 @@ void corsConfigurationShouldAllowCredentials() throws Exception { Method corsConfigurationSourceMethod = SecurityConfiguration.class.getDeclaredMethod("corsConfigurationSource"); corsConfigurationSourceMethod.setAccessible(true); CorsConfigurationSource corsConfigurationSource = (CorsConfigurationSource) corsConfigurationSourceMethod.invoke(securityConfiguration); - + MockHttpServletRequest request = new MockHttpServletRequest(); var corsConfiguration = corsConfigurationSource.getCorsConfiguration(request); @@ -125,7 +126,7 @@ void corsConfigurationShouldHaveCorrectMaxAge() throws Exception { Method corsConfigurationSourceMethod = SecurityConfiguration.class.getDeclaredMethod("corsConfigurationSource"); corsConfigurationSourceMethod.setAccessible(true); CorsConfigurationSource corsConfigurationSource = (CorsConfigurationSource) corsConfigurationSourceMethod.invoke(securityConfiguration); - + MockHttpServletRequest request = new MockHttpServletRequest(); var corsConfiguration = corsConfigurationSource.getCorsConfiguration(request); From 16f90fccb29ceca04faf996282941e817c30afe4 Mon Sep 17 00:00:00 2001 From: "fernanda.mello" Date: Sat, 6 Sep 2025 15:50:20 -0300 Subject: [PATCH 2/3] feat: Renomeia classes e implementa testes unitarios --- .../src/application/clients/IbgeClient.java | 26 ++-- ...onController.java => StateController.java} | 27 ++-- ...ponseDTO.java => CityIbgeResponseDTO.java} | 2 +- ...LocationDataDTO.java => StateDataDTO.java} | 2 +- ...onseDTO.java => StateIbgeResponseDTO.java} | 15 ++- .../src/application/dto/StateResponseDTO.java | 13 +- .../application/services/LocationService.java | 22 ---- .../application/services/StateService.java | 22 ++++ .../application/clients/IbgeClientTest.java | 117 ++++++++++++++++++ .../controllers/StateControllerTest.java | 95 ++++++++++++++ .../application}/dto/PointRequestDTOTest.java | 9 +- .../dto/PointResponseDTOTest.java | 9 +- .../application}/mapper/PointMapperTest.java | 7 +- .../services}/PointServiceTest.java | 41 +++--- .../services/StateServiceTest.java | 55 ++++++++ .../src/test/resources/application.properties | 6 +- 16 files changed, 371 insertions(+), 97 deletions(-) rename pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/{LocationController.java => StateController.java} (54%) rename pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/{CityResponseDTO.java => CityIbgeResponseDTO.java} (90%) rename pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/{LocationDataDTO.java => StateDataDTO.java} (88%) rename pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/{LocationResponseDTO.java => StateIbgeResponseDTO.java} (50%) delete mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/application/services/LocationService.java create mode 100644 pointtils/src/main/java/com/pointtils/pointtils/src/application/services/StateService.java create mode 100644 pointtils/src/test/java/com/pointtils/pointtils/src/application/clients/IbgeClientTest.java create mode 100644 pointtils/src/test/java/com/pointtils/pointtils/src/application/controllers/StateControllerTest.java rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/application}/dto/PointRequestDTOTest.java (92%) rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/application}/dto/PointResponseDTOTest.java (95%) rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/application}/mapper/PointMapperTest.java (96%) rename pointtils/src/test/java/com/pointtils/pointtils/{ => src/application/services}/PointServiceTest.java (98%) create mode 100644 pointtils/src/test/java/com/pointtils/pointtils/src/application/services/StateServiceTest.java diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/clients/IbgeClient.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/clients/IbgeClient.java index d4d2350a..57baeeaf 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/clients/IbgeClient.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/clients/IbgeClient.java @@ -1,8 +1,8 @@ package com.pointtils.pointtils.src.application.clients; -import com.pointtils.pointtils.src.application.dto.CityResponseDTO; -import com.pointtils.pointtils.src.application.dto.LocationDataDTO; -import com.pointtils.pointtils.src.application.dto.StateResponseDTO; +import com.pointtils.pointtils.src.application.dto.CityIbgeResponseDTO; +import com.pointtils.pointtils.src.application.dto.StateDataDTO; +import com.pointtils.pointtils.src.application.dto.StateIbgeResponseDTO; import com.pointtils.pointtils.src.core.domain.exceptions.ClientTimeoutException; import jakarta.persistence.EntityNotFoundException; import lombok.extern.slf4j.Slf4j; @@ -35,11 +35,11 @@ public IbgeClient(@Qualifier("ibgeRestTemplate") RestTemplate restTemplate, this.cityUrl = cityUrl; } - public List getStateList() { + public List getStateList() { try { log.info("Iniciando uma requisicao para a API do IBGE para buscar a lista de UFs"); - ResponseEntity stateResponse = restTemplate.getForEntity(stateUrl, StateResponseDTO[].class); - Function mapper = state -> new LocationDataDTO(state.getAbbreviation()); + ResponseEntity stateResponse = restTemplate.getForEntity(stateUrl, StateIbgeResponseDTO[].class); + Function mapper = state -> new StateDataDTO(state.getAbbreviation()); return formatResponseData(stateResponse.getBody(), mapper, "UFs não encontradas"); } catch (ResourceAccessException ex) { log.error("Timeout na requisicao para a API do IBGE para buscar a lista de UFs", ex); @@ -47,11 +47,11 @@ public List getStateList() { } } - public List getCityListByState(String state) { + public List getCityListByState(String state) { try { log.info("Iniciando uma requisicao para a API do IBGE para buscar a lista de municípios da UF {}", state); - ResponseEntity cityResponse = restTemplate.getForEntity(cityUrl, CityResponseDTO[].class, state); - Function mapper = city -> new LocationDataDTO(city.getName()); + ResponseEntity cityResponse = restTemplate.getForEntity(cityUrl, CityIbgeResponseDTO[].class, state); + Function mapper = city -> new StateDataDTO(city.getName()); return formatResponseData(cityResponse.getBody(), mapper, "Municípios não encontrados"); } catch (ResourceAccessException ex) { log.error("Timeout na requisicao para a API do IBGE para buscar a lista de municípios da UF {}", state, ex); @@ -59,15 +59,15 @@ public List getCityListByState(String state) { } } - private List formatResponseData(T[] responseBody, - Function mapper, - String errorMessage) { + private List formatResponseData(T[] responseBody, + Function mapper, + String errorMessage) { if (ArrayUtils.isEmpty(responseBody)) { throw new EntityNotFoundException(errorMessage); } return Arrays.stream(responseBody) .map(mapper) - .sorted(Comparator.comparing(LocationDataDTO::getName)) + .sorted(Comparator.comparing(StateDataDTO::getName)) .toList(); } } diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/LocationController.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/StateController.java similarity index 54% rename from pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/LocationController.java rename to pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/StateController.java index 9d010bdd..cbd8c228 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/LocationController.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/controllers/StateController.java @@ -1,7 +1,7 @@ package com.pointtils.pointtils.src.application.controllers; -import com.pointtils.pointtils.src.application.dto.LocationResponseDTO; -import com.pointtils.pointtils.src.application.services.LocationService; +import com.pointtils.pointtils.src.application.dto.StateResponseDTO; +import com.pointtils.pointtils.src.application.services.StateService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; @@ -15,25 +15,24 @@ @RestController @RequiredArgsConstructor -@RequestMapping("/v1/location") -@Tag(name = "Location Controller", description = "Endpoints para gerenciar dados de localização") -public class LocationController { +@RequestMapping("/v1/states") +@SecurityRequirement(name = "bearerAuth") +@Tag(name = "State Controller", description = "Endpoints para gerenciar dados de UFs brasileiras") +public class StateController { - private final LocationService locationService; + private final StateService stateService; - @GetMapping("/states") + @GetMapping @ResponseStatus(HttpStatus.OK) - @SecurityRequirement(name = "bearerAuth") @Operation(summary = "Busca todas as UFs brasileiras") - public LocationResponseDTO getStates() { - return locationService.getAllStates(); + public StateResponseDTO getStates() { + return stateService.getAllStates(); } - @GetMapping("/states/{stateId}/cities") + @GetMapping("/{stateId}/cities") @ResponseStatus(HttpStatus.OK) - @SecurityRequirement(name = "bearerAuth") @Operation(summary = "Busca todos os municípios de uma determinada UF brasileira") - public LocationResponseDTO getCitiesByState(@PathVariable String stateId) { - return locationService.getCitiesByState(stateId); + public StateResponseDTO getCitiesByState(@PathVariable String stateId) { + return stateService.getCitiesByState(stateId); } } diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityResponseDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityIbgeResponseDTO.java similarity index 90% rename from pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityResponseDTO.java rename to pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityIbgeResponseDTO.java index a6f71b76..5963dd68 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityResponseDTO.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/CityIbgeResponseDTO.java @@ -10,7 +10,7 @@ @Setter @NoArgsConstructor @AllArgsConstructor -public class CityResponseDTO { +public class CityIbgeResponseDTO { private Long id; diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationDataDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateDataDTO.java similarity index 88% rename from pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationDataDTO.java rename to pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateDataDTO.java index ac7c1880..cf305877 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationDataDTO.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateDataDTO.java @@ -9,7 +9,7 @@ @Setter @NoArgsConstructor @AllArgsConstructor -public class LocationDataDTO { +public class StateDataDTO { private String name; } diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationResponseDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateIbgeResponseDTO.java similarity index 50% rename from pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationResponseDTO.java rename to pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateIbgeResponseDTO.java index 6fd7477a..09c810c5 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/LocationResponseDTO.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateIbgeResponseDTO.java @@ -1,19 +1,22 @@ package com.pointtils.pointtils.src.application.dto; +import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import java.util.List; - @Getter @Setter @NoArgsConstructor @AllArgsConstructor -public class LocationResponseDTO { +public class StateIbgeResponseDTO { + + private Long id; + + @JsonProperty("sigla") + private String abbreviation; - private boolean success; - private String message; - private List data; + @JsonProperty("nome") + private String name; } diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateResponseDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateResponseDTO.java index 4195ea0b..7e6a92c8 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateResponseDTO.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/StateResponseDTO.java @@ -1,22 +1,19 @@ package com.pointtils.pointtils.src.application.dto; -import com.fasterxml.jackson.annotation.JsonProperty; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; +import java.util.List; + @Getter @Setter @NoArgsConstructor @AllArgsConstructor public class StateResponseDTO { - private Long id; - - @JsonProperty("sigla") - private String abbreviation; - - @JsonProperty("nome") - private String name; + private boolean success; + private String message; + private List data; } diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/LocationService.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/LocationService.java deleted file mode 100644 index c0fd83ed..00000000 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/LocationService.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.pointtils.pointtils.src.application.services; - -import com.pointtils.pointtils.src.application.clients.IbgeClient; -import com.pointtils.pointtils.src.application.dto.LocationResponseDTO; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class LocationService { - - private final IbgeClient ibgeClient; - - public LocationResponseDTO getAllStates() { - return new LocationResponseDTO(true, "UFs encontradas com sucesso", ibgeClient.getStateList()); - } - - public LocationResponseDTO getCitiesByState(String state) { - return new LocationResponseDTO(true, "Municípios encontrados com sucesso", - ibgeClient.getCityListByState(state)); - } -} diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/StateService.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/StateService.java new file mode 100644 index 00000000..d7408054 --- /dev/null +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/services/StateService.java @@ -0,0 +1,22 @@ +package com.pointtils.pointtils.src.application.services; + +import com.pointtils.pointtils.src.application.clients.IbgeClient; +import com.pointtils.pointtils.src.application.dto.StateResponseDTO; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class StateService { + + private final IbgeClient ibgeClient; + + public StateResponseDTO getAllStates() { + return new StateResponseDTO(true, "UFs encontradas com sucesso", ibgeClient.getStateList()); + } + + public StateResponseDTO getCitiesByState(String state) { + return new StateResponseDTO(true, "Municípios encontrados com sucesso", + ibgeClient.getCityListByState(state)); + } +} diff --git a/pointtils/src/test/java/com/pointtils/pointtils/src/application/clients/IbgeClientTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/clients/IbgeClientTest.java new file mode 100644 index 00000000..7aa88a65 --- /dev/null +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/clients/IbgeClientTest.java @@ -0,0 +1,117 @@ +package com.pointtils.pointtils.src.application.clients; + +import com.pointtils.pointtils.src.application.dto.CityIbgeResponseDTO; +import com.pointtils.pointtils.src.application.dto.StateIbgeResponseDTO; +import com.pointtils.pointtils.src.core.domain.exceptions.ClientTimeoutException; +import jakarta.persistence.EntityNotFoundException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.ResourceAccessException; +import org.springframework.web.client.RestTemplate; + +import java.net.SocketTimeoutException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class IbgeClientTest { + + @Mock + private RestTemplate restTemplate; + private IbgeClient ibgeClient; + + @BeforeEach + void setUp() { + this.ibgeClient = new IbgeClient(restTemplate, "http://exemplo.com.br/estados", + "http://exemplo.com.br/estados/{state}/municipios"); + } + + @Test + @DisplayName("Deve obter da API externa a lista de UFs em ordem alfabética") + void shouldGetStateListInAlphabeticalOrder() { + var mockRsResponse = new StateIbgeResponseDTO(1L, "RS", "Rio Grande do Sul"); + var mockAcreResponse = new StateIbgeResponseDTO(2L, "AC", "Acre"); + when(restTemplate.getForEntity("http://exemplo.com.br/estados", StateIbgeResponseDTO[].class)) + .thenReturn(ResponseEntity.ok(new StateIbgeResponseDTO[]{mockRsResponse, mockAcreResponse})); + + var actualResponse = ibgeClient.getStateList(); + assertEquals(2, actualResponse.size()); + assertEquals("AC", actualResponse.get(0).getName()); + assertEquals("RS", actualResponse.get(1).getName()); + } + + @Test + @DisplayName("Deve lancar EntityNotFoundException se API externa retornar lista de UFs nula") + void shouldGetEntityNotFoundExceptionIfStateListIsNull() { + when(restTemplate.getForEntity("http://exemplo.com.br/estados", StateIbgeResponseDTO[].class)) + .thenReturn(ResponseEntity.ok(null)); + + assertThrows(EntityNotFoundException.class, () -> ibgeClient.getStateList()); + } + + @Test + @DisplayName("Deve lancar EntityNotFoundException se API externa retornar lista de UFs vazia") + void shouldGetEntityNotFoundExceptionIfStateListIsEmpty() { + when(restTemplate.getForEntity("http://exemplo.com.br/estados", StateIbgeResponseDTO[].class)) + .thenReturn(ResponseEntity.ok(new StateIbgeResponseDTO[]{})); + + assertThrows(EntityNotFoundException.class, () -> ibgeClient.getStateList()); + } + + @Test + @DisplayName("Deve lancar ClientTimeoutException se ocorrer timeout em chamada da API externa para obter UFs") + void shouldGetClientTimeoutExceptionIfStateListRequestTimeout() { + when(restTemplate.getForEntity("http://exemplo.com.br/estados", StateIbgeResponseDTO[].class)) + .thenThrow(new ResourceAccessException("Erro", new SocketTimeoutException("Timeout"))); + + assertThrows(ClientTimeoutException.class, () -> ibgeClient.getStateList()); + } + + @Test + @DisplayName("Deve obter da API externa a lista de municípios por UF em ordem alfabética") + void shouldGetCityListInAlphabeticalOrder() { + var mockCityResponse1 = new CityIbgeResponseDTO(1L, "Porto Alegre"); + var mockCityResponse2 = new CityIbgeResponseDTO(2L, "Canoas"); + when(restTemplate.getForEntity("http://exemplo.com.br/estados/{state}/municipios", CityIbgeResponseDTO[].class, "RS")) + .thenReturn(ResponseEntity.ok(new CityIbgeResponseDTO[]{mockCityResponse1, mockCityResponse2})); + + var actualResponse = ibgeClient.getCityListByState("RS"); + assertEquals(2, actualResponse.size()); + assertEquals("Canoas", actualResponse.get(0).getName()); + assertEquals("Porto Alegre", actualResponse.get(1).getName()); + } + + @Test + @DisplayName("Deve lancar EntityNotFoundException se API externa retornar lista de municípios nula") + void shouldGetEntityNotFoundExceptionIfCityListIsNull() { + when(restTemplate.getForEntity("http://exemplo.com.br/estados/{state}/municipios", CityIbgeResponseDTO[].class, "RS")) + .thenReturn(ResponseEntity.ok(null)); + + assertThrows(EntityNotFoundException.class, () -> ibgeClient.getCityListByState("RS")); + } + + @Test + @DisplayName("Deve lancar EntityNotFoundException se API externa retornar lista de municípios vazia") + void shouldGetEntityNotFoundExceptionIfCityListIsEmpty() { + when(restTemplate.getForEntity("http://exemplo.com.br/estados/{state}/municipios", CityIbgeResponseDTO[].class, "RS")) + .thenReturn(ResponseEntity.ok(new CityIbgeResponseDTO[]{})); + + assertThrows(EntityNotFoundException.class, () -> ibgeClient.getCityListByState("RS")); + } + + @Test + @DisplayName("Deve lancar ClientTimeoutException se ocorrer timeout em chamada da API externa para obter municípios") + void shouldGetClientTimeoutExceptionIfCityListRequestTimeout() { + when(restTemplate.getForEntity("http://exemplo.com.br/estados/{state}/municipios", CityIbgeResponseDTO[].class, "RS")) + .thenThrow(new ResourceAccessException("Erro", new SocketTimeoutException("Timeout"))); + + assertThrows(ClientTimeoutException.class, () -> ibgeClient.getCityListByState("RS")); + } +} diff --git a/pointtils/src/test/java/com/pointtils/pointtils/src/application/controllers/StateControllerTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/controllers/StateControllerTest.java new file mode 100644 index 00000000..fb578abc --- /dev/null +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/controllers/StateControllerTest.java @@ -0,0 +1,95 @@ +package com.pointtils.pointtils.src.application.controllers; + +import com.pointtils.pointtils.src.application.dto.StateDataDTO; +import com.pointtils.pointtils.src.application.dto.StateResponseDTO; +import com.pointtils.pointtils.src.application.services.StateService; +import com.pointtils.pointtils.src.infrastructure.configs.GlobalExceptionHandler; +import com.pointtils.pointtils.src.infrastructure.configs.JwtAuthenticationFilter; +import com.pointtils.pointtils.src.infrastructure.configs.JwtService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.http.HttpHeaders; +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; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@ActiveProfiles("test") +@SpringBootTest(classes = StateController.class) +@Import(JwtAuthenticationFilter.class) +class StateControllerTest { + + @MockitoBean + private JwtService jwtService; + @MockitoBean + private StateService stateService; + + @Autowired + private JwtAuthenticationFilter jwtAuthenticationFilter; + + @Autowired + private StateController stateController; + + private MockMvc mockMvc; + + @BeforeEach + void setup() { + this.mockMvc = MockMvcBuilders.standaloneSetup(stateController) + .setControllerAdvice(new GlobalExceptionHandler()) + .apply(springSecurity(jwtAuthenticationFilter)) + .build(); + when(jwtService.isTokenExpired(anyString())).thenReturn(Boolean.FALSE); + } + + @Test + @DisplayName("Deve retornar 200 e a lista de estados ao chamar o endpoint /v1/states") + void shouldGetOkResponseForGetStatesEndpoint() throws Exception { + StateResponseDTO mockResponse = new StateResponseDTO(true, "Sucesso", + List.of(new StateDataDTO("RS"))); + + when(stateService.getAllStates()).thenReturn(mockResponse); + + mockMvc.perform(MockMvcRequestBuilders + .get("/v1/states") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer valid_token")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.success").value(true)) + .andExpect(jsonPath("$.message").value("Sucesso")) + .andExpect(jsonPath("$.data[0].name").value("RS")); + } + + @Test + @DisplayName("Deve retornar 200 e a lista de municípios ao chamar o endpoint /v1/states/{id}/cities") + void shouldGetOkResponseForGetCitiesByStateEndpoint() throws Exception { + StateResponseDTO mockResponse = new StateResponseDTO(true, "Sucesso", + List.of(new StateDataDTO("Porto Alegre"))); + + when(stateService.getCitiesByState("RS")).thenReturn(mockResponse); + + mockMvc.perform(MockMvcRequestBuilders + .get("/v1/states/RS/cities") + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON) + .header(HttpHeaders.AUTHORIZATION, "Bearer valid_token")) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.success").value(true)) + .andExpect(jsonPath("$.message").value("Sucesso")) + .andExpect(jsonPath("$.data[0].name").value("Porto Alegre")); + } +} diff --git a/pointtils/src/test/java/com/pointtils/pointtils/dto/PointRequestDTOTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointRequestDTOTest.java similarity index 92% rename from pointtils/src/test/java/com/pointtils/pointtils/dto/PointRequestDTOTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointRequestDTOTest.java index dd3c852c..2fd97b4c 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/dto/PointRequestDTOTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointRequestDTOTest.java @@ -1,9 +1,12 @@ -package com.pointtils.pointtils.dto; +package com.pointtils.pointtils.src.application.dto; -import com.pointtils.pointtils.src.application.dto.PointRequestDTO; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; class PointRequestDTOTest { diff --git a/pointtils/src/test/java/com/pointtils/pointtils/dto/PointResponseDTOTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointResponseDTOTest.java similarity index 95% rename from pointtils/src/test/java/com/pointtils/pointtils/dto/PointResponseDTOTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointResponseDTOTest.java index a91957bf..3cbd6755 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/dto/PointResponseDTOTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointResponseDTOTest.java @@ -1,11 +1,14 @@ -package com.pointtils.pointtils.dto; +package com.pointtils.pointtils.src.application.dto; -import com.pointtils.pointtils.src.application.dto.PointResponseDTO; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; class PointResponseDTOTest { diff --git a/pointtils/src/test/java/com/pointtils/pointtils/mapper/PointMapperTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/mapper/PointMapperTest.java similarity index 96% rename from pointtils/src/test/java/com/pointtils/pointtils/mapper/PointMapperTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/application/mapper/PointMapperTest.java index 715fb828..a622c257 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/mapper/PointMapperTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/mapper/PointMapperTest.java @@ -1,8 +1,7 @@ -package com.pointtils.pointtils.mapper; +package com.pointtils.pointtils.src.application.mapper; import com.pointtils.pointtils.src.application.dto.PointRequestDTO; import com.pointtils.pointtils.src.application.dto.PointResponseDTO; -import com.pointtils.pointtils.src.application.mapper.PointMapper; import com.pointtils.pointtils.src.core.domain.entities.Point; import com.pointtils.pointtils.src.core.domain.entities.PointType; import org.junit.jupiter.api.BeforeEach; @@ -10,7 +9,9 @@ import java.time.LocalDateTime; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; class PointMapperTest { diff --git a/pointtils/src/test/java/com/pointtils/pointtils/PointServiceTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/services/PointServiceTest.java similarity index 98% rename from pointtils/src/test/java/com/pointtils/pointtils/PointServiceTest.java rename to pointtils/src/test/java/com/pointtils/pointtils/src/application/services/PointServiceTest.java index ce7f66ef..55845e03 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/PointServiceTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/services/PointServiceTest.java @@ -1,18 +1,12 @@ -package com.pointtils.pointtils; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.List; -import java.util.Optional; +package com.pointtils.pointtils.src.application.services; +import com.pointtils.pointtils.src.application.dto.PointRequestDTO; +import com.pointtils.pointtils.src.application.dto.PointResponseDTO; +import com.pointtils.pointtils.src.application.mapper.PointMapper; +import com.pointtils.pointtils.src.core.domain.entities.Point; +import com.pointtils.pointtils.src.core.domain.entities.PointType; +import com.pointtils.pointtils.src.infrastructure.repositories.PointRepository; +import jakarta.persistence.EntityNotFoundException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -20,15 +14,18 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import com.pointtils.pointtils.src.application.dto.PointRequestDTO; -import com.pointtils.pointtils.src.application.dto.PointResponseDTO; -import com.pointtils.pointtils.src.application.mapper.PointMapper; -import com.pointtils.pointtils.src.application.services.PointService; -import com.pointtils.pointtils.src.core.domain.entities.Point; -import com.pointtils.pointtils.src.core.domain.entities.PointType; -import com.pointtils.pointtils.src.infrastructure.repositories.PointRepository; +import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; -import jakarta.persistence.EntityNotFoundException; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class PointServiceTest { diff --git a/pointtils/src/test/java/com/pointtils/pointtils/src/application/services/StateServiceTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/services/StateServiceTest.java new file mode 100644 index 00000000..6130e2dc --- /dev/null +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/services/StateServiceTest.java @@ -0,0 +1,55 @@ +package com.pointtils.pointtils.src.application.services; + +import com.pointtils.pointtils.src.application.clients.IbgeClient; +import com.pointtils.pointtils.src.application.dto.StateDataDTO; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class StateServiceTest { + + @Mock + private IbgeClient ibgeClient; + @InjectMocks + private StateService stateService; + + @Test + @DisplayName("Deve buscar todas as UFs") + void shouldGetAllStates() { + var firstMockedData = new StateDataDTO("RS"); + var secondMockedData = new StateDataDTO("SC"); + when(ibgeClient.getStateList()).thenReturn(List.of(firstMockedData, secondMockedData)); + + var response = stateService.getAllStates(); + assertTrue(response.isSuccess()); + assertEquals("UFs encontradas com sucesso", response.getMessage()); + assertThat(response.getData()) + .hasSize(2) + .containsExactly(firstMockedData, secondMockedData); + } + + @Test + @DisplayName("Deve buscar todos os municípios de uma determinada UF") + void shouldGetCitiesByState() { + var firstMockedData = new StateDataDTO("Porto Alegre"); + when(ibgeClient.getCityListByState("RS")).thenReturn(List.of(firstMockedData)); + + var response = stateService.getCitiesByState("RS"); + assertTrue(response.isSuccess()); + assertEquals("Municípios encontrados com sucesso", response.getMessage()); + assertThat(response.getData()) + .hasSize(1) + .containsExactly(firstMockedData); + } +} diff --git a/pointtils/src/test/resources/application.properties b/pointtils/src/test/resources/application.properties index 63cf81b2..b55d8b95 100644 --- a/pointtils/src/test/resources/application.properties +++ b/pointtils/src/test/resources/application.properties @@ -23,4 +23,8 @@ spring.flyway.enabled=false # Swagger/OpenAPI Configuration (disabled for tests) springdoc.api-docs.enabled=false springdoc.swagger-ui.enabled=false -springdoc.swagger-ui.path=/swagger-ui.html \ No newline at end of file +springdoc.swagger-ui.path=/swagger-ui.html + +# Clientes HTTP +client.ibge.state-url=http://exemplo.com.br/estados +client.ibge.city-url=http://exemplo.com.br/estados/{state}/municipios \ No newline at end of file From 7e01aa5477d46d0ae6364f23170f5815ae9142b6 Mon Sep 17 00:00:00 2001 From: "fernanda.mello" Date: Sat, 6 Sep 2025 16:19:29 -0300 Subject: [PATCH 3/3] fix: Corrige erros de compilacao em DEV --- .../src/application/dto/PointRequestDTO.java | 2 +- .../src/application/dto/PointResponseDTO.java | 2 +- .../src/core/domain/entities/Point.java | 2 +- .../application/dto/PointRequestDTOTest.java | 30 ++++----- .../application/dto/PointResponseDTOTest.java | 38 ++++++------ .../application/mapper/PointMapperTest.java | 62 ++++--------------- .../services/PointServiceTest.java | 6 +- 7 files changed, 51 insertions(+), 91 deletions(-) diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/PointRequestDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/PointRequestDTO.java index 5b8395ff..00956d96 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/PointRequestDTO.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/PointRequestDTO.java @@ -11,7 +11,7 @@ @NoArgsConstructor @AllArgsConstructor public class PointRequestDTO { - private String userId; + private Long userId; private String description; private String type; // ENTRY, EXIT, LUNCH_START, LUNCH_END } diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/PointResponseDTO.java b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/PointResponseDTO.java index f37401b7..5f26f470 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/PointResponseDTO.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/application/dto/PointResponseDTO.java @@ -13,7 +13,7 @@ @AllArgsConstructor public class PointResponseDTO { private Long id; - private String userId; + private Long userId; private String description; private LocalDateTime timestamp; private String type; diff --git a/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/entities/Point.java b/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/entities/Point.java index bda1930c..86a6ed00 100644 --- a/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/entities/Point.java +++ b/pointtils/src/main/java/com/pointtils/pointtils/src/core/domain/entities/Point.java @@ -24,7 +24,7 @@ public class Point { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private String userId; + private Long userId; private String description; private LocalDateTime timestamp; private String type; // ENTRY, EXIT, LUNCH_START, LUNCH_END diff --git a/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointRequestDTOTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointRequestDTOTest.java index 2fd97b4c..70d72c23 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointRequestDTOTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointRequestDTOTest.java @@ -13,7 +13,7 @@ class PointRequestDTOTest { @Test void shouldCreatePointRequestDTOWithAllArgsConstructor() { // Given - String userId = "user123"; + Long userId = 1L; String description = "Test description"; String type = "ENTRY"; @@ -42,7 +42,7 @@ void shouldCreatePointRequestDTOWithNoArgsConstructor() { @Test void shouldCreatePointRequestDTOWithBuilder() { // Given - String userId = "user123"; + Long userId = 1L; String description = "Test description"; String type = "ENTRY"; @@ -64,7 +64,7 @@ void shouldCreatePointRequestDTOWithBuilder() { void shouldSetAndGetProperties() { // Given PointRequestDTO dto = new PointRequestDTO(); - String userId = "user123"; + Long userId = 1L; String description = "Test description"; String type = "ENTRY"; @@ -93,10 +93,10 @@ void shouldHandleNullValues() { @Test void shouldHandleEmptyStrings() { // Given - PointRequestDTO dto = new PointRequestDTO("", "", ""); + PointRequestDTO dto = new PointRequestDTO(1L, "", ""); // Then - assertEquals("", dto.getUserId()); + assertEquals(1L, dto.getUserId()); assertEquals("", dto.getDescription()); assertEquals("", dto.getType()); } @@ -104,14 +104,14 @@ void shouldHandleEmptyStrings() { @Test void shouldGenerateToString() { // Given - PointRequestDTO dto = new PointRequestDTO("user123", "Test description", "ENTRY"); + PointRequestDTO dto = new PointRequestDTO(1L, "Test description", "ENTRY"); // When String toString = dto.toString(); // Then assertNotNull(toString); - assertTrue(toString.contains("user123")); + assertTrue(toString.contains("1")); assertTrue(toString.contains("Test description")); assertTrue(toString.contains("ENTRY")); } @@ -119,8 +119,8 @@ void shouldGenerateToString() { @Test void shouldGenerateHashCode() { // Given - PointRequestDTO dto1 = new PointRequestDTO("user123", "Test description", "ENTRY"); - PointRequestDTO dto2 = new PointRequestDTO("user123", "Test description", "ENTRY"); + PointRequestDTO dto1 = new PointRequestDTO(1L, "Test description", "ENTRY"); + PointRequestDTO dto2 = new PointRequestDTO(1L, "Test description", "ENTRY"); // When int hashCode1 = dto1.hashCode(); @@ -133,8 +133,8 @@ void shouldGenerateHashCode() { @Test void shouldBeEqualWithSameValues() { // Given - PointRequestDTO dto1 = new PointRequestDTO("user123", "Test description", "ENTRY"); - PointRequestDTO dto2 = new PointRequestDTO("user123", "Test description", "ENTRY"); + PointRequestDTO dto1 = new PointRequestDTO(1L, "Test description", "ENTRY"); + PointRequestDTO dto2 = new PointRequestDTO(1L, "Test description", "ENTRY"); // Then assertEquals(dto1, dto2); @@ -143,8 +143,8 @@ void shouldBeEqualWithSameValues() { @Test void shouldNotBeEqualWithDifferentValues() { // Given - PointRequestDTO dto1 = new PointRequestDTO("user123", "Test description", "ENTRY"); - PointRequestDTO dto2 = new PointRequestDTO("user456", "Different description", "EXIT"); + PointRequestDTO dto1 = new PointRequestDTO(1L, "Test description", "ENTRY"); + PointRequestDTO dto2 = new PointRequestDTO(2L, "Different description", "EXIT"); // Then assertNotEquals(dto1, dto2); @@ -153,7 +153,7 @@ void shouldNotBeEqualWithDifferentValues() { @Test void shouldNotBeEqualWithNull() { // Given - PointRequestDTO dto = new PointRequestDTO("user123", "Test description", "ENTRY"); + PointRequestDTO dto = new PointRequestDTO(1L, "Test description", "ENTRY"); // Then assertNotEquals(null, dto); @@ -162,7 +162,7 @@ void shouldNotBeEqualWithNull() { @Test void shouldNotBeEqualWithDifferentClass() { // Given - PointRequestDTO dto = new PointRequestDTO("user123", "Test description", "ENTRY"); + PointRequestDTO dto = new PointRequestDTO(1L, "Test description", "ENTRY"); String differentObject = "not a dto"; // Then diff --git a/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointResponseDTOTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointResponseDTOTest.java index 3cbd6755..11796fab 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointResponseDTOTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/dto/PointResponseDTOTest.java @@ -16,7 +16,7 @@ class PointResponseDTOTest { void shouldCreatePointResponseDTOWithAllArgsConstructor() { // Given Long id = 1L; - String userId = "user123"; + Long userId = 1L; String description = "Test description"; LocalDateTime timestamp = LocalDateTime.now(); String type = "ENTRY"; @@ -51,7 +51,7 @@ void shouldCreatePointResponseDTOWithNoArgsConstructor() { void shouldCreatePointResponseDTOWithBuilder() { // Given Long id = 1L; - String userId = "user123"; + Long userId = 1L; String description = "Test description"; LocalDateTime timestamp = LocalDateTime.now(); String type = "ENTRY"; @@ -79,7 +79,7 @@ void shouldSetAndGetProperties() { // Given PointResponseDTO dto = new PointResponseDTO(); Long id = 1L; - String userId = "user123"; + Long userId = 1L; String description = "Test description"; LocalDateTime timestamp = LocalDateTime.now(); String type = "ENTRY"; @@ -116,11 +116,11 @@ void shouldHandleNullValues() { void shouldHandleEmptyStrings() { // Given LocalDateTime timestamp = LocalDateTime.now(); - PointResponseDTO dto = new PointResponseDTO(1L, "", "", timestamp, ""); + PointResponseDTO dto = new PointResponseDTO(1L, 1L, "", timestamp, ""); // Then assertEquals(1L, dto.getId()); - assertEquals("", dto.getUserId()); + assertEquals(1L, dto.getUserId()); assertEquals("", dto.getDescription()); assertEquals(timestamp, dto.getTimestamp()); assertEquals("", dto.getType()); @@ -130,7 +130,7 @@ void shouldHandleEmptyStrings() { void shouldGenerateToString() { // Given LocalDateTime timestamp = LocalDateTime.now(); - PointResponseDTO dto = new PointResponseDTO(1L, "user123", "Test description", timestamp, "ENTRY"); + PointResponseDTO dto = new PointResponseDTO(1L, 2L, "Test description", timestamp, "ENTRY"); // When String toString = dto.toString(); @@ -138,7 +138,7 @@ void shouldGenerateToString() { // Then assertNotNull(toString); assertTrue(toString.contains("1")); - assertTrue(toString.contains("user123")); + assertTrue(toString.contains("2")); assertTrue(toString.contains("Test description")); assertTrue(toString.contains("ENTRY")); } @@ -147,8 +147,8 @@ void shouldGenerateToString() { void shouldGenerateHashCode() { // Given LocalDateTime timestamp = LocalDateTime.now(); - PointResponseDTO dto1 = new PointResponseDTO(1L, "user123", "Test description", timestamp, "ENTRY"); - PointResponseDTO dto2 = new PointResponseDTO(1L, "user123", "Test description", timestamp, "ENTRY"); + PointResponseDTO dto1 = new PointResponseDTO(1L, 1L, "Test description", timestamp, "ENTRY"); + PointResponseDTO dto2 = new PointResponseDTO(1L, 1L, "Test description", timestamp, "ENTRY"); // When int hashCode1 = dto1.hashCode(); @@ -162,8 +162,8 @@ void shouldGenerateHashCode() { void shouldBeEqualWithSameValues() { // Given LocalDateTime timestamp = LocalDateTime.now(); - PointResponseDTO dto1 = new PointResponseDTO(1L, "user123", "Test description", timestamp, "ENTRY"); - PointResponseDTO dto2 = new PointResponseDTO(1L, "user123", "Test description", timestamp, "ENTRY"); + PointResponseDTO dto1 = new PointResponseDTO(1L, 1L, "Test description", timestamp, "ENTRY"); + PointResponseDTO dto2 = new PointResponseDTO(1L, 1L, "Test description", timestamp, "ENTRY"); // Then assertEquals(dto1, dto2); @@ -173,8 +173,8 @@ void shouldBeEqualWithSameValues() { void shouldNotBeEqualWithDifferentValues() { // Given LocalDateTime timestamp = LocalDateTime.now(); - PointResponseDTO dto1 = new PointResponseDTO(1L, "user123", "Test description", timestamp, "ENTRY"); - PointResponseDTO dto2 = new PointResponseDTO(2L, "user456", "Different description", timestamp, "EXIT"); + PointResponseDTO dto1 = new PointResponseDTO(1L, 1L, "Test description", timestamp, "ENTRY"); + PointResponseDTO dto2 = new PointResponseDTO(2L, 2L, "Different description", timestamp, "EXIT"); // Then assertNotEquals(dto1, dto2); @@ -185,8 +185,8 @@ void shouldNotBeEqualWithDifferentTimestamps() { // Given LocalDateTime timestamp1 = LocalDateTime.now(); LocalDateTime timestamp2 = timestamp1.plusMinutes(1); - PointResponseDTO dto1 = new PointResponseDTO(1L, "user123", "Test description", timestamp1, "ENTRY"); - PointResponseDTO dto2 = new PointResponseDTO(1L, "user123", "Test description", timestamp2, "ENTRY"); + PointResponseDTO dto1 = new PointResponseDTO(1L, 1L, "Test description", timestamp1, "ENTRY"); + PointResponseDTO dto2 = new PointResponseDTO(1L, 1L, "Test description", timestamp2, "ENTRY"); // Then assertNotEquals(dto1, dto2); @@ -196,7 +196,7 @@ void shouldNotBeEqualWithDifferentTimestamps() { void shouldNotBeEqualWithNull() { // Given LocalDateTime timestamp = LocalDateTime.now(); - PointResponseDTO dto = new PointResponseDTO(1L, "user123", "Test description", timestamp, "ENTRY"); + PointResponseDTO dto = new PointResponseDTO(1L, 1L, "Test description", timestamp, "ENTRY"); // Then assertNotEquals(null, dto); @@ -206,7 +206,7 @@ void shouldNotBeEqualWithNull() { void shouldNotBeEqualWithDifferentClass() { // Given LocalDateTime timestamp = LocalDateTime.now(); - PointResponseDTO dto = new PointResponseDTO(1L, "user123", "Test description", timestamp, "ENTRY"); + PointResponseDTO dto = new PointResponseDTO(1L, 1L, "Test description", timestamp, "ENTRY"); String differentObject = "not a dto"; // Then @@ -217,8 +217,8 @@ void shouldNotBeEqualWithDifferentClass() { void shouldHandleNullIdInEquality() { // Given LocalDateTime timestamp = LocalDateTime.now(); - PointResponseDTO dto1 = new PointResponseDTO(null, "user123", "Test description", timestamp, "ENTRY"); - PointResponseDTO dto2 = new PointResponseDTO(null, "user123", "Test description", timestamp, "ENTRY"); + PointResponseDTO dto1 = new PointResponseDTO(null, 1L, "Test description", timestamp, "ENTRY"); + PointResponseDTO dto2 = new PointResponseDTO(null, 1L, "Test description", timestamp, "ENTRY"); // Then assertEquals(dto1, dto2); diff --git a/pointtils/src/test/java/com/pointtils/pointtils/src/application/mapper/PointMapperTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/mapper/PointMapperTest.java index a622c257..6c090d86 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/src/application/mapper/PointMapperTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/mapper/PointMapperTest.java @@ -25,14 +25,14 @@ void setUp() { @Test void shouldMapPointRequestDTOToPoint() { // Given - PointRequestDTO requestDTO = new PointRequestDTO("user123", "Test description", "ENTRY"); + PointRequestDTO requestDTO = new PointRequestDTO(1L, "Test description", "ENTRY"); // When Point point = pointMapper.toEntity(requestDTO); // Then assertNotNull(point); - assertEquals("user123", point.getUserId()); + assertEquals(1L, point.getUserId()); assertEquals("Test description", point.getDescription()); assertEquals(PointType.ENTRY, point.getType()); assertNotNull(point.getTimestamp()); @@ -41,14 +41,14 @@ void shouldMapPointRequestDTOToPoint() { @Test void shouldMapPointRequestDTOToPointWithExitType() { // Given - PointRequestDTO requestDTO = new PointRequestDTO("user123", "Test description", "EXIT"); + PointRequestDTO requestDTO = new PointRequestDTO(1L, "Test description", "EXIT"); // When Point point = pointMapper.toEntity(requestDTO); // Then assertNotNull(point); - assertEquals("user123", point.getUserId()); + assertEquals(1L, point.getUserId()); assertEquals("Test description", point.getDescription()); assertEquals(PointType.EXIT, point.getType()); assertNotNull(point.getTimestamp()); @@ -73,14 +73,13 @@ void shouldMapPointRequestDTOToPointWithNullValues() { @Test void shouldMapPointRequestDTOToPointWithEmptyStrings() { // Given - PointRequestDTO requestDTO = new PointRequestDTO("", "", "ENTRY"); + PointRequestDTO requestDTO = new PointRequestDTO(1L, "", "ENTRY"); // When Point point = pointMapper.toEntity(requestDTO); // Then assertNotNull(point); - assertEquals("", point.getUserId()); assertEquals("", point.getDescription()); assertEquals(PointType.ENTRY, point.getType()); assertNotNull(point.getTimestamp()); @@ -92,7 +91,7 @@ void shouldMapPointToPointResponseDTO() { LocalDateTime timestamp = LocalDateTime.now(); Point point = new Point(); point.setId(1L); - point.setUserId("user123"); + point.setUserId(1L); point.setDescription("Test description"); point.setTimestamp(timestamp); point.setType(PointType.ENTRY); @@ -103,7 +102,7 @@ void shouldMapPointToPointResponseDTO() { // Then assertNotNull(responseDTO); assertEquals(1L, responseDTO.getId()); - assertEquals("user123", responseDTO.getUserId()); + assertEquals(1L, responseDTO.getUserId()); assertEquals("Test description", responseDTO.getDescription()); assertEquals(timestamp, responseDTO.getTimestamp()); assertEquals("ENTRY", responseDTO.getType()); @@ -115,7 +114,7 @@ void shouldMapPointToPointResponseDTOWithExitType() { LocalDateTime timestamp = LocalDateTime.now(); Point point = new Point(); point.setId(1L); - point.setUserId("user123"); + point.setUserId(1L); point.setDescription("Test description"); point.setTimestamp(timestamp); point.setType(PointType.EXIT); @@ -126,7 +125,7 @@ void shouldMapPointToPointResponseDTOWithExitType() { // Then assertNotNull(responseDTO); assertEquals(1L, responseDTO.getId()); - assertEquals("user123", responseDTO.getUserId()); + assertEquals(1L, responseDTO.getUserId()); assertEquals("Test description", responseDTO.getDescription()); assertEquals(timestamp, responseDTO.getTimestamp()); assertEquals("EXIT", responseDTO.getType()); @@ -155,58 +154,19 @@ void shouldMapPointToPointResponseDTOWithNullValues() { assertNull(responseDTO.getType()); } - @Test - void shouldHandleNullValuesInPointRequestDTO() { - // Given - PointRequestDTO requestDTO = new PointRequestDTO(null, null, null); - - // When - Point point = pointMapper.toEntity(requestDTO); - - // Then - assertNotNull(point); - assertNull(point.getUserId()); - assertNull(point.getDescription()); - assertNull(point.getType()); - assertNotNull(point.getTimestamp()); - } - @Test void shouldHandleEmptyStringsInPointRequestDTO() { // Given - PointRequestDTO requestDTO = new PointRequestDTO("", "", "ENTRY"); + PointRequestDTO requestDTO = new PointRequestDTO(1L, "", "ENTRY"); // When Point point = pointMapper.toEntity(requestDTO); // Then assertNotNull(point); - assertEquals("", point.getUserId()); + assertEquals(1L, point.getUserId()); assertEquals("", point.getDescription()); assertEquals(PointType.ENTRY, point.getType()); assertNotNull(point.getTimestamp()); } - - @Test - void shouldHandleNullValuesInPoint() { - // Given - LocalDateTime timestamp = LocalDateTime.now(); - Point point = new Point(); - point.setId(null); - point.setUserId(null); - point.setDescription(null); - point.setTimestamp(timestamp); - point.setType(null); - - // When - PointResponseDTO responseDTO = pointMapper.toResponseDTO(point); - - // Then - assertNotNull(responseDTO); - assertNull(responseDTO.getId()); - assertNull(responseDTO.getUserId()); - assertNull(responseDTO.getDescription()); - assertEquals(timestamp, responseDTO.getTimestamp()); - assertNull(responseDTO.getType()); - } } diff --git a/pointtils/src/test/java/com/pointtils/pointtils/src/application/services/PointServiceTest.java b/pointtils/src/test/java/com/pointtils/pointtils/src/application/services/PointServiceTest.java index 55845e03..0f0defd8 100644 --- a/pointtils/src/test/java/com/pointtils/pointtils/src/application/services/PointServiceTest.java +++ b/pointtils/src/test/java/com/pointtils/pointtils/src/application/services/PointServiceTest.java @@ -48,19 +48,19 @@ void setUp() { // Configurar objetos de teste point = new Point(); point.setId(1L); - point.setUserId("user123"); + point.setUserId(1L); point.setDescription("Morning entry"); point.setType(PointType.ENTRY); point.setTimestamp(LocalDateTime.now()); requestDTO = new PointRequestDTO(); - requestDTO.setUserId("user123"); + requestDTO.setUserId(1L); requestDTO.setDescription("Morning entry"); requestDTO.setType(PointType.ENTRY); responseDTO = new PointResponseDTO(); responseDTO.setId(1L); - responseDTO.setUserId("user123"); + responseDTO.setUserId(1L); responseDTO.setDescription("Morning entry"); responseDTO.setType(PointType.ENTRY); responseDTO.setTimestamp(point.getTimestamp());