handleFailures(Exception exception) {
+ ExceptionDTO dto = new ExceptionDTO(exception.getMessage(), HttpStatus.BAD_REQUEST.value());
+ return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(dto);
+ }
+
+ /**
+ * Método que manipula as exceções específicas da {@link ConstructorDefaultUndefinedException}
+ * que podem ocorrer ao instanciar objetos sem um construtor padrão. Quando essa exceção
+ * é lançada, este método a capturará e retornará uma resposta HTTP adequada usando
+ * o {@link ExceptionDTO} para transmitir as informações da exceção.
+ *
+ * Este método é anotado com {@code @ExceptionHandler}, que é uma anotação Springer,
+ * significando que o Springer invocará automaticamente este método para tratar as exceções do
+ * tipo {@link ConstructorDefaultUndefinedException} lançadas por qualquer método do controlador
+ * respectivo.
+ *
+ * @param exception A exceção específica do {@link ConstructorDefaultUndefinedException} que ocorreu.
+ * @return Uma resposta HTTP encapsulada em uma {@link ResponseEntity} que contém o DTO da exceção,
+ * composto pela mensagem da exceção e um código de status HTTP. O status HTTP da resposta é
+ * o mesmo que o status HTTP da exceção.
+ */
+ @ExceptionHandler(ConstructorDefaultUndefinedException.class)
+ public ResponseEntity handleMapperFailures(ConstructorDefaultUndefinedException exception) {
+ ExceptionDTO dto = new ExceptionDTO(exception.getMessage(), ConstructorDefaultUndefinedException.ERROR.getStatusCodeValue());
+ return ResponseEntity.status(ConstructorDefaultUndefinedException.ERROR.getHttpStatusCode()).body(dto);
+ }
+
+ /**
+ * Manipula as exceções específicas de {@link ShelterEntityFailuresException} que
+ * podem ocorrer durante a manipulação dos dados da entidade de abrigo. Quando uma dessas exceções
+ * é lançada, este método irá capturá-la e retornar uma resposta adequada usando o {@link ExceptionDTO}
+ * para transportar as informações de exceção.
+ *
+ * O método é anotado com {@code @ExceptionHandler}, o que significa que será invocado automaticamente
+ * pelo Spring para tratar exceções do tipo {@link ShelterEntityFailuresException} lançadas
+ * por qualquer método do respectivo controlador.
+ *
+ * @param exception A exceção específica do {@link ShelterEntityFailuresException} que ocorreu.
+ * @return Uma resposta HTTP representada como {@link ResponseEntity} contendo o DTO de exceção
+ * que contém a mensagem da exceção e um código de status HTTP. O status HTTP da resposta será
+ * o mesmo que o status HTTP da exceção.
+ */
+ @ExceptionHandler(ShelterEntityFailuresException.class)
+ public ResponseEntity handleShelterEntityFailures(ShelterEntityFailuresException exception) {
+ ExceptionDTO dto = new ExceptionDTO(exception.getMessage(), ShelterEntityFailuresException.ERROR.getStatusCodeValue());
+ return ResponseEntity.status(ShelterEntityFailuresException.ERROR.getHttpStatusCode()).body(dto);
+ }
+
+ /**
+ * Manipula as exceções específicas de {@link AddressEntityFailuresException} que
+ * podem ocorrer durante a manipulação dos dados da entidade de endereço. Quando uma dessas exceções
+ * é lançada, esse método irá capturá-la e retornar uma resposta adequada usando o {@link ExceptionDTO}
+ * para transportar as informações de exceção.
+ *
+ * O método é anotado com {@code @ExceptionHandler}, o que significa que será invocado automaticamente
+ * pelo Spring para tratar exceções do tipo {@link AddressEntityFailuresException} lançadas
+ * por qualquer método do respectivo controlador.
+ *
+ * @param exception A exceção específica do {@link AddressEntityFailuresException} que ocorreu.
+ * @return Uma resposta HTTP representada como {@link ResponseEntity} contendo o DTO de exceção
+ * que contém a mensagem da exceção e um código de status HTTP.
+ * O status HTTP da resposta será o mesmo que o status HTTP da exceção.
+ */
+ @ExceptionHandler(AddressEntityFailuresException.class)
+ public ResponseEntity handleAddressEntityFailures(AddressEntityFailuresException exception) {
+ ExceptionDTO dto = new ExceptionDTO(exception.getMessage(), AddressEntityFailuresException.ERROR.getStatusCodeValue());
+ return ResponseEntity.status(AddressEntityFailuresException.ERROR.getHttpStatusCode()).body(dto);
+ }
+
+ /**
+ * Manipula a exceção {@link MapperFailureException} e retorna uma resposta de erro adequada.
+ *
+ * Este método é usado para tratar as exceções específicas do {@link MapperFailureException}
+ * que podem ocorrer durante a operação de mapeamento de classes. Quando uma dessas exceções é lançada,
+ * esse método irá capturá-la e retornar uma resposta adequada usando o {@link ExceptionDTO} para
+ * transportar as informações de exceção.
+ *
+ * O método é anotado com {@code @ExceptionHandler}, o que significa que será invocado automaticamente
+ * pelo Spring para tratar exceções do tipo {@link MapperFailureException} lançadas por qualquer
+ * método do controlador.
+ *
+ * @param exception A exceção específica do {@link MapperFailureException} que ocorreu.
+ * @return Uma resposta HTTP representada como {@link ResponseEntity} contendo o DTO de exceção que
+ * contém a mensagem da exceção e um código de status HTTP. O status HTTP da resposta será
+ * o mesmo que o status HTTP da exceção.
+ */
+ @ExceptionHandler(MapperFailureException.class)
+ public ResponseEntity handleMapperFailures(MapperFailureException exception) {
+ ExceptionDTO dto = new ExceptionDTO(exception.getMessage(), MapperFailureException.ERROR.getStatusCodeValue());
+ return ResponseEntity.status(MapperFailureException.ERROR.getHttpStatusCode()).body(dto);
+ }
+
+ /**
+ * Este método é usado para manipular as exceções específicas de {@link UserEntityFailuresException}
+ * que podem ocorrer durante a manipulação dos dados do {@link UserEntity}. Quando uma dessas exceções é lançada,
+ * esse método irá capturá-la e retornar uma resposta adequada usando o {@link ExceptionDTO}
+ * para transportar as informações de exceção.
+ *
+ * O método é anotado com {@code @ExceptionHandler}, o que significa que será invocado automaticamente
+ * pelo Spring para tratar exceções do tipo {@link UserEntityFailuresException} lançadas por qualquer
+ * método do controlador.
+ *
+ * @param exception A exceção específica do {@link UserEntityFailuresException} que ocorreu.
+ * @return Uma resposta HTTP representada como ResponseEntity contendo o DTO de exceção que contém a
+ * mensagem da exceção e um código de status HTTP. O status HTTP da resposta será o mesmo que
+ * o status HTTP da exceção.
+ */
+ @ExceptionHandler(UserEntityFailuresException.class)
+ public ResponseEntity handleUserEntityFailures(UserEntityFailuresException exception) {
+ ExceptionDTO dto = new ExceptionDTO(exception.getMessage(), UserEntityFailuresException.ERROR.getStatusCodeValue());
+ return ResponseEntity.status(UserEntityFailuresException.ERROR.getHttpStatusCode()).body(dto);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/config/web/OpenApiConfig.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/config/web/OpenApiConfig.java
index 9095b7c..e0bcb49 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/config/web/OpenApiConfig.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/config/web/OpenApiConfig.java
@@ -59,8 +59,8 @@ private Info getInfo() {
*/
private List getTags() {
return List.of(
- new Tag().name("Doadores").description("Funcionalidades direcionadas para os Doadores"),
- new Tag().name("Receptores").description("Funcionalidades direcionadas para os Receptores"));
+ new Tag().name("Usuários").description("Funcionalidades direcionadas para os Usuários"),
+ new Tag().name("Abrigos").description("Funcionalidades direcionadas para os Abrigos"));
}
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/ShelterController.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/ShelterController.java
new file mode 100644
index 0000000..14bc15c
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/ShelterController.java
@@ -0,0 +1,80 @@
+package diegosneves.github.conectardoacoes.adapters.rest.controller;
+
+import diegosneves.github.conectardoacoes.adapters.rest.request.ShelterCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.ShelterCreatedResponse;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.server.ResponseStatusException;
+
+/**
+ * Interface que define as operações de gerenciamento de abrigos.
+ *
+ * Esta interface representa o controlador que manipula todas as operações relacionadas aos abrigos
+ * em nosso sistema. Define como o cliente (geralmente um front-end da web)
+ * deve interfacear com os serviços de back-end para criar e administrar abrigos.
+ *
+ * As operações principais que ela define incluem a criação de novos abrigos,
+ * através de solicitações HTTP POST para a rota "/ create".
+ * A especificação completa dessas rotas e do códigos de status HTTP que eles podem retornar,
+ * encontra-se nos Javadoc dos métodos individuais.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public interface ShelterController {
+
+ /**
+ * Método POST para a criação de um Abrigo.
+ *
+ * Este método recebe um objeto JSON que representa uma solicitação de criação de abrigo,
+ * a criação do abrigo é realizada no back-end, e retorna uma resposta que inclui os
+ * detalhes do abrigo criado.
+ *
+ * O objeto de solicitação deve ser fornecido no corpo da solicitação, com os seguintes campos:
+ *
+ * - {@code shelterName}: Nome do abrigo a ser criado.
+ * - {@code address}: Um objeto que representa o endereço do abrigo. Deve incluir rua, número, bairro,
+ * cidade, estado e CEP.
+ * - {@code responsibleUserEmail}: O e-mail do usuário responsável pelo abrigo.
+ *
+ *
+ * O método retornará um objeto JSON com os seguintes campos:
+ *
+ * - {@code id}: O ID gerado para o novo abrigo criado.
+ * - {@code shelterName}: O nome do abrigo criado.
+ * - {@code address}: Um objeto representando o endereço do abrigo criado.
+ * - {@code responsibleUser}: Um objeto representando o usuário responsável pelo abrigo.
+ *
+ *
+ * @param request objeto {@link ShelterCreationRequest} que representa a solicitação de criação de
+ * um abrigo que é mapeada do corpo da solicitação JSON.
+ * @return Retorna um {@link ResponseEntity} que encapsula a resposta da criação do abrigo. Esta
+ * resposta inclui o status HTTP da operação, bem como um corpo que é uma representação JSON
+ * do abrigo criado.
+ * @throws ResponseStatusException será lançada se a criação do abrigo falhar devido a
+ * problemas de validação ou problemas no servidor. A mensagem de erro será incluída na
+ * exceção.
+ */
+ @PostMapping(value = "/create", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
+ @Operation(
+ summary = "Criar Abrigo",
+ description = "Este endpoint é responsável por criar e registrar um novo Abrigo no sistema utilizando os dados recebidos por meio de uma requisição POST",
+ tags = "Abrigos"
+ )
+ @ApiResponses(value = {
+ @ApiResponse(
+ responseCode = "201",
+ description = "Abrigo criado com sucesso!",
+ content = @Content(schema = @Schema(implementation = ShelterCreatedResponse.class))
+ )
+ })
+ ResponseEntity createShelter(@RequestBody ShelterCreationRequest request);
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/UserController.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/UserController.java
new file mode 100644
index 0000000..fc48969
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/UserController.java
@@ -0,0 +1,77 @@
+package diegosneves.github.conectardoacoes.adapters.rest.controller;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.request.UserEntityCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.UserEntityCreatedResponse;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+/**
+ * A interface {@link UserController} age como um controlador REST referente a usuários dentro deste sistema.
+ * Seu propósito é fornecer endpoints que lidam com todas as operações relativas aos usuários (como, por exemplo, criação de novo usuário), realizando a ligação entre as requisições HTTP dos clientes e a camada de serviço do sistema.
+ *
+ *
+ * Dentro desta interface, são definidos métodos para lidar com uma série de operações de usuário, como a criação de um usuário novo.
+ * Cada método está atrelado a um endpoint específico e é responsável por manipular uma operação distinta.
+ * Um exemplo é o método {@link #createUser(UserEntityCreationRequest)}, que está mapeado para o endpoint "create" e é responsável pela criação de um novo usuário no sistema.
+ *
+ *
+ * Como uma interface de controlador REST, processa-se input no formato JSON e devolve-se dados também no formato JSON.
+ * A conversão entre este formato de dados e os objetos do domínio do sistema se dá através de classes de solicitação e resposta (como {@link UserEntityCreationRequest} e {@link UserEntityCreatedResponse}), que atuam como DTOs (Data Transfer Objects) que facilitam a serialização e deserialização de dados e validam a estrutura desses dados.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public interface UserController {
+
+ /**
+ * Este endpoint pertence à aplicação "Usuários".
+ * Responsável por registrar novos usuários no sistema.
+ * Aceita uma requisição POST com o objeto {@link UserEntityCreationRequest} no corpo que contém as informações do usuário a ser registrado.
+ *
+ *
+ * Após a criação bem-sucedida do usuário, retorna um objeto {@link ResponseEntity} que encapsula os detalhes da criação do usuário na forma de {@link UserEntityCreatedResponse}.
+ *
+ * O objeto {@link UserEntityCreatedResponse} é um DTO que contém os detalhes relevantes sobre o usuário que foi criado.
+ * Isso inclui o ID de usuário único gerado pelo sistema, o nome de usuário escolhido, o endereço de e-mail fornecido e o tipo de perfil associado a este usuário.
+ *
+ *
+ * Em qualquer caso de violação das validações de integridade do modelo da entidade, um erro HTTP apropriado é retornado junto com os detalhes do erro.
+ *
+ * @param request um objeto {@link UserEntityCreationRequest} encapsulando os detalhes do novo usuário a ser registrado.
+ * Este parâmetro deve estar presente no corpo da solicitação POST e é deserializado para o tipo {@link UserEntityCreationRequest}.
+ * @return {@link ResponseEntity} que encapsula o {@link UserEntityCreatedResponse} se o usuário for criado com sucesso.
+ * @see UserEntityCreatedResponse
+ * @see UserEntityCreationRequest
+ */
+ @PostMapping(value = "create", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
+ @Operation(
+ summary = "Criar Usuário",
+ description = "Este endpoint é responsável por criar e registrar um novo Usuário no sistema utilizando os dados recebidos por meio de uma requisição POST",
+ tags = "Usuários",
+ parameters = {
+ @Parameter(
+ name = "Perfil do usuário",
+ description = "O campo 'userProfile' só permite dois valores possíveis: 'Doador' ou 'Beneficiário'.",
+ schema = @Schema(implementation = UserProfileType.class)
+ )
+ }
+ )
+ @ApiResponses(value = {
+ @ApiResponse(
+ responseCode = "201",
+ description = "Usuário criado com sucesso!",
+ content = @Content(schema = @Schema(implementation = UserEntityCreatedResponse.class))
+ )
+ })
+ ResponseEntity createUser(@RequestBody UserEntityCreationRequest request);
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/imp/ShelterControllerImpl.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/imp/ShelterControllerImpl.java
new file mode 100644
index 0000000..e4205ac
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/imp/ShelterControllerImpl.java
@@ -0,0 +1,45 @@
+package diegosneves.github.conectardoacoes.adapters.rest.controller.imp;
+
+
+import diegosneves.github.conectardoacoes.adapters.rest.controller.ShelterController;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.request.ShelterCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.ShelterCreatedResponse;
+import diegosneves.github.conectardoacoes.adapters.rest.service.ShelterEntityService;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * A classe {@link ShelterControllerImpl} implementa a interface {@link ShelterController} e serve como
+ * o ponto de entrada da API para o gerenciamento dos abrigos.
+ *
+ * Esta classe é decorada com as anotações {@code @RestController} e {@code @RequestMapping("/shelter")},
+ * indicando que é um controlador REST e que irá responder a requisições feitas para /shelter.
+ *
+ * @author diegoneves
+ * @see ShelterController
+ * @see ShelterEntityService
+ * @see ShelterCreationRequest
+ * @see ShelterCreatedResponse
+ * @see ShelterEntityFailuresException
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/shelter")
+public class ShelterControllerImpl implements ShelterController {
+
+ private final ShelterEntityService shelterEntityService;
+
+ public ShelterControllerImpl(ShelterEntityService shelterEntityService) {
+ this.shelterEntityService = shelterEntityService;
+ }
+
+ @Override
+ public ResponseEntity createShelter(ShelterCreationRequest request) {
+ ShelterCreatedResponse response = this.shelterEntityService.createShelter(request);
+ return ResponseEntity.status(HttpStatus.CREATED).body(response);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/imp/UserControllerImpl.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/imp/UserControllerImpl.java
new file mode 100644
index 0000000..d31ef2d
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/controller/imp/UserControllerImpl.java
@@ -0,0 +1,41 @@
+package diegosneves.github.conectardoacoes.adapters.rest.controller.imp;
+
+import diegosneves.github.conectardoacoes.adapters.rest.controller.UserController;
+import diegosneves.github.conectardoacoes.adapters.rest.request.UserEntityCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.UserEntityCreatedResponse;
+import diegosneves.github.conectardoacoes.adapters.rest.service.UserEntityService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * Esta é a classe {@link UserControllerImpl} que implementa a interface {@link UserController}.
+ * É anotada com {@link RestController}, o que significa que é um controlador de serviço web em que
+ * cada método retorna um objeto de domínio (Entity) ao invés de uma view.
+ * É responsável por lidar com todas as requisições HTTP que são enviadas para a URL {@code "/user"}.
+ *
+ * Possui uma instância da classe de serviço {@link UserEntityService}, que é usada para implementar
+ * a lógica de negócios relacionada aos usuários.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+@RestController
+@RequestMapping("/user")
+public class UserControllerImpl implements UserController {
+
+ private final UserEntityService service;
+
+ @Autowired
+ public UserControllerImpl(UserEntityService service) {
+ this.service = service;
+ }
+
+ @Override
+ public ResponseEntity createUser(UserEntityCreationRequest request) {
+ UserEntityCreatedResponse newUserResponse = this.service.createUserEntity(request);
+ return ResponseEntity.status(HttpStatus.CREATED).body(newUserResponse);
+ }
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/dto/AddressDTO.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/dto/AddressDTO.java
new file mode 100644
index 0000000..6133fec
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/dto/AddressDTO.java
@@ -0,0 +1,44 @@
+package diegosneves.github.conectardoacoes.adapters.rest.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Classe modelo {@code DTO} para o endereço. Contém informações básicas de endereço, como rua, número, bairro,
+ * cidade, estado e CEP.
+ *
+ * Uso:
+ *
+ * {@code
+ * AddressDTO address = AddressDTO.builder()
+ * .street("Main St")
+ * .number("42")
+ * .neighborhood("Centro")
+ * .city("Rio de Janeiro")
+ * .state("RJ")
+ * .zip("20031-040")
+ * .build();
+ * }
+ *
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Builder
+public class AddressDTO {
+
+ private String street;
+ private String number;
+ private String neighborhood;
+ private String city;
+ private String state;
+ private String zip;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/dto/ExceptionDTO.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/dto/ExceptionDTO.java
new file mode 100644
index 0000000..9f74c94
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/dto/ExceptionDTO.java
@@ -0,0 +1,12 @@
+package diegosneves.github.conectardoacoes.adapters.rest.dto;
+
+/**
+ * A classe {@link ExceptionDTO} representa um objeto de transferência de dados
+ * para transportar informações de exceção.
+ * Ela contém a mensagem e o código de status da exceção.
+ *
+ * @author diegosneves
+ * @since 1.0.0
+ */
+public record ExceptionDTO(String message, int statusCode) {
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/dto/UserEntityDTO.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/dto/UserEntityDTO.java
new file mode 100644
index 0000000..db87eee
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/dto/UserEntityDTO.java
@@ -0,0 +1,47 @@
+package diegosneves.github.conectardoacoes.adapters.rest.dto;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+
+/**
+ * Classe modelo {@code DTO} para um usuário. Contém informações básicas sobre um usuário,
+ * incluindo o {@code id} do usuário, o {@code nome do usuário}, o {@code e-mail} e o
+ * {@code tipo de perfil do usuário}.
+ *
+ * Os tipos de perfil de usuário são definidos na enumeração {@link UserProfileType}. Os tipos atuais de perfil
+ * suportados são {@code 'Doador'} e {@code 'Beneficiário'}.
+ *
+ * Por exemplo, para criar uma instância de UserEntityDTO, você pode usar:
+ *
+ * {@code
+ * UserEntityDTO user = UserEntityDTO.builder()
+ * .id("3f2f8ab2-e9ee-41fa-af8a-b2e9ee91fac7")
+ * .userName("John Doe")
+ * .email("john.doe@example.com")
+ * .userProfile(UserProfileType.DONOR) // pode ser DONOR ou BENEFICIARY
+ * .build();
+ * }
+ *
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ * @see UserProfileType
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Builder
+public class UserEntityDTO {
+
+ private String id;
+ private String userName;
+ private String email;
+ private UserProfileType userProfile;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/enums/ExceptionDetails.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/enums/ExceptionDetails.java
new file mode 100644
index 0000000..f7b8c3e
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/enums/ExceptionDetails.java
@@ -0,0 +1,59 @@
+package diegosneves.github.conectardoacoes.adapters.rest.enums;
+
+import org.springframework.http.HttpStatus;
+
+/**
+ * A classe {@link ExceptionDetails} é uma enumeração que define várias mensagens de exceções.
+ * Cada mensagem corresponde a uma condição específica de validação ou erro
+ * que pode ocorrer durante as operações.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public enum ExceptionDetails {
+
+ CONSTRUCTOR_DEFAULT_UNDEFINED("Classe [ %s ] deve declarar um construtor padrão.", HttpStatus.NOT_IMPLEMENTED),
+ CLASS_MAPPING_FAILURE("Falha ao tentar mapear a classe [ %s ].", HttpStatus.BAD_REQUEST),
+ SHELTER_OPERATION_FAILURE("Ocorreu um erro ao realizar uma operação no Abrigo. Motivo: %s", HttpStatus.BAD_REQUEST),
+ ADDRESS_OPERATION_FAILURE("Ocorreu um erro ao realizar uma operação no Endereço. Motivo: %s", HttpStatus.BAD_REQUEST),
+ USER_OPERATION_FAILURE("Ocorreu um erro ao realizar uma operação com o Usuário. Motivo: %s", HttpStatus.BAD_REQUEST),
+ INVALID_UUID_FORMAT_MESSAGE("O ID %s precisa estar no formato UUID", HttpStatus.INTERNAL_SERVER_ERROR);
+
+ private final String message;
+ private final HttpStatus httpStatus;
+
+ ExceptionDetails(String message, HttpStatus httpStatus) {
+ this.message = message;
+ this.httpStatus = httpStatus;
+ }
+
+
+ /**
+ * Formata uma mensagem com a entrada fornecida e retorna a mensagem formatada.
+ *
+ * @param message A mensagem de entrada que será formatada.
+ * @return A mensagem após a formatação.
+ */
+ public String formatErrorMessage(String message) {
+ return String.format(this.message, message);
+ }
+
+ /**
+ * Retorna o código de status HTTP associado ao erro.
+ *
+ * @return O código numérico do status HTTP relacionado com o erro.
+ */
+ public int getStatusCodeValue() {
+ return this.httpStatus.value();
+ }
+
+ /**
+ * Obtém o status HTTP associado ao erro.
+ *
+ * @return O código de status HTTP relacionado ao erro.
+ */
+ public HttpStatus getHttpStatusCode() {
+ return this.httpStatus;
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/enums/UserProfileType.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/enums/UserProfileType.java
new file mode 100644
index 0000000..9625b2a
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/enums/UserProfileType.java
@@ -0,0 +1,19 @@
+package diegosneves.github.conectardoacoes.adapters.rest.enums;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+/**
+ * A enumeração {@link UserProfileType} fornece os tipos de perfis disponíveis para um usuário.
+ * Os perfis disponíveis são {@code 'Doador'} e {@code 'Beneficiário'}.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public enum UserProfileType {
+
+ @JsonProperty(value = "Doador")
+ DONOR,
+ @JsonProperty(value = "Beneficiário")
+ BENEFICIARY;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/AddressEntityFailuresException.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/AddressEntityFailuresException.java
new file mode 100644
index 0000000..3fdb817
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/AddressEntityFailuresException.java
@@ -0,0 +1,56 @@
+package diegosneves.github.conectardoacoes.adapters.rest.exception;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.ExceptionDetails;
+
+/**
+ * A classe {@link AddressEntityFailuresException} é uma subclasse da classe {@link RuntimeException}.
+ * Esta é uma exceção personalizada que é lançada quando ocorre um erro durante a execução de uma operação
+ * relacionada a uma entidade de endereço, como mapeamento ou validação.
+ *
+ * As mensagens de erro personalizadas para esta exceção são definidas através das constantes na enumeração
+ * {@link ExceptionDetails}. A mensagem de erro específica usada neste caso é a
+ * {@link ExceptionDetails#ADDRESS_OPERATION_FAILURE}.
+ *
+ * Sendo uma {@link RuntimeException}, não é obrigatório que seja declarada na cláusula `throws` dos métodos
+ * que a lançam, e ela não precisa ser capturada explicitamente.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ * @see RuntimeException
+ */
+public class AddressEntityFailuresException extends RuntimeException {
+
+ public static final ExceptionDetails ERROR = ExceptionDetails.ADDRESS_OPERATION_FAILURE;
+
+ /**
+ * Este construtor para a classe {@link AddressEntityFailuresException} recebe uma string
+ * que representa uma mensagem personalizada de erro. A mensagem fornecida é então formatada
+ * por meio do método {@code ERROR.formatErrorMessage(message)}, onde {@code ERROR} é uma
+ * constante da enumeração {@link ExceptionDetails}, especificamente
+ * {@link ExceptionDetails#ADDRESS_OPERATION_FAILURE}, que guarda detalhes para uma operação
+ * de endereço que falhou.
+ *
+ * A mensagem formatada é então passada para o construtor da superclasse {@link RuntimeException}
+ * através da chamada {@code super()}.
+ *
+ * @param message A mensagem personalizada de erro que será formatada e passada
+ * para a superclasse {@link RuntimeException}.
+ * @throws NullPointerException se a mensagem fornecida for {@code null}.
+ */
+ public AddressEntityFailuresException(String message) {
+ super(ERROR.formatErrorMessage(message));
+ }
+
+ /**
+ * Construtor que recebe uma mensagem de erro e uma exceção causal. Invoca o construtor de sua classe
+ * mãe {@link RuntimeException} passando uma mensagem de erro formatada e a exceção causal.
+ * A mensagem de erro é formatada usando o método {@code ERROR.formatErrorMessage(message)}, onde {@code ERROR}
+ * é a constante {@link ExceptionDetails} especificada para operações de endereço que falham.
+ *
+ * @param message A mensagem de erro personalizada.
+ * @param cause A exceção causal.
+ */
+ public AddressEntityFailuresException(String message, Throwable cause) {
+ super(ERROR.formatErrorMessage(message), cause);
+ }
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/ConstructorDefaultUndefinedException.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/ConstructorDefaultUndefinedException.java
new file mode 100644
index 0000000..2c0d83b
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/ConstructorDefaultUndefinedException.java
@@ -0,0 +1,35 @@
+package diegosneves.github.conectardoacoes.adapters.rest.exception;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.ExceptionDetails;
+
+/**
+ * Exceção personalizada que é lançada quando não é definido um construtor padrão.
+ *
+ * @see RuntimeException
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class ConstructorDefaultUndefinedException extends RuntimeException {
+
+ public static final ExceptionDetails ERROR = ExceptionDetails.CONSTRUCTOR_DEFAULT_UNDEFINED;
+
+ /**
+ * Construtor da exceção {@link ConstructorDefaultUndefinedException}.
+ *
+ * @param message a mensagem de detalhe da exceção.
+ */
+ public ConstructorDefaultUndefinedException(String message) {
+ super(ERROR.formatErrorMessage(message));
+ }
+
+ /**
+ * Construtor da exceção {@link ConstructorDefaultUndefinedException}.
+ *
+ * @param message a mensagem de detalhe da exceção.
+ * @param e a causa da exceção.
+ */
+ public ConstructorDefaultUndefinedException(String message, Throwable e) {
+ super(ERROR.formatErrorMessage(message), e);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/MapperFailureException.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/MapperFailureException.java
new file mode 100644
index 0000000..b62843f
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/MapperFailureException.java
@@ -0,0 +1,31 @@
+package diegosneves.github.conectardoacoes.adapters.rest.exception;
+
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.ExceptionDetails;
+
+/**
+ * {@link MapperFailureException} é uma classe de exceção personalizada. Ela tem como finalidade gerenciar
+ * falhas ocorridas durante o processo de mapeamento, e proporcionar mensagens de erro mais detalhadas.
+ * Herdando de {@link RuntimeException}, ela representa exceções em tempo de execução que podem ser lançadas
+ * durante a operação normal da JVM.
+ *
+ * @see RuntimeException
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class MapperFailureException extends RuntimeException {
+
+ public static final ExceptionDetails ERROR = ExceptionDetails.CLASS_MAPPING_FAILURE;
+
+ /**
+ * Esta é uma classe de exceção personalizada usada para gerenciar e fornecer mensagens mais
+ * informativas quando uma falha ocorre durante o mapeamento.
+ *
+ * @param message A mensagem específica da exceção.
+ * @param e A exceção generica causada durante o mapeamento.
+ */
+ public MapperFailureException(String message, Throwable e) {
+ super(ERROR.formatErrorMessage(message), e);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/ShelterEntityFailuresException.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/ShelterEntityFailuresException.java
new file mode 100644
index 0000000..55058a0
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/ShelterEntityFailuresException.java
@@ -0,0 +1,42 @@
+package diegosneves.github.conectardoacoes.adapters.rest.exception;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.ExceptionDetails;
+import diegosneves.github.conectardoacoes.adapters.rest.model.ShelterEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
+
+/**
+ * A classe {@link ShelterEntityFailuresException} representa uma exceção específica que será lançada
+ * quando ocorrer uma falha em uma operação relacionada ao {@link ShelterEntity}.
+ * Herda de {@link RuntimeException} e adiciona mensagens de erro detalhadas para os erros que podem ocorrer
+ * durante as operações de manipulação dos dados da entidade {@link Shelter}.
+ *
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class ShelterEntityFailuresException extends RuntimeException {
+
+ public static final ExceptionDetails ERROR = ExceptionDetails.SHELTER_OPERATION_FAILURE;
+
+ /**
+ * Uma exceção que será lançada quando ocorrer uma falha em uma operação relacionada ao {@link ShelterEntity}.
+ * A exceção contém uma mensagem de erro detalhada.
+ *
+ * @param message A mensagem específica da exceção.
+ */
+ public ShelterEntityFailuresException(String message) {
+ super(ERROR.formatErrorMessage(message));
+ }
+
+ /**
+ * Uma exceção que será lançada quando ocorrer uma falha em uma operação relacionada ao {@link ShelterEntity}.
+ * A exceção contém uma mensagem de erro detalhada e a causa original do erro.
+ *
+ * @param message A mensagem específica da exceção.
+ * @param cause A causa original do erro.
+ */
+ public ShelterEntityFailuresException(String message, Throwable cause) {
+ super(ERROR.formatErrorMessage(message), cause);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/UserEntityFailuresException.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/UserEntityFailuresException.java
new file mode 100644
index 0000000..4db2deb
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/exception/UserEntityFailuresException.java
@@ -0,0 +1,44 @@
+package diegosneves.github.conectardoacoes.adapters.rest.exception;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.ExceptionDetails;
+import diegosneves.github.conectardoacoes.adapters.rest.model.ShelterEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+
+/**
+ * A classe {@link UserEntityFailuresException} representa uma exceção específica que será lançada
+ * quando ocorrer uma falha em uma operação relacionada ao {@link UserEntity}.
+ * Herda de {@link RuntimeException} e adiciona mensagens de erro detalhadas para os erros que podem ocorrer
+ * durante as operações de manipulação dos dados da entidade {@link User}.
+ *
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class UserEntityFailuresException extends RuntimeException {
+
+ public static final ExceptionDetails ERROR = ExceptionDetails.USER_OPERATION_FAILURE;
+
+ /**
+ * Uma exceção que será lançada quando ocorrer uma falha em uma operação relacionada ao {@link UserEntity}.
+ * A exceção contém uma mensagem de erro detalhada.
+ *
+ * @param message A mensagem específica da exceção.
+ */
+ public UserEntityFailuresException(String message) {
+ super(ERROR.formatErrorMessage(message));
+ }
+
+ /**
+ * Uma exceção que será lançada quando ocorrer uma falha em uma operação relacionada ao {@link UserEntity}.
+ * A exceção contém uma mensagem de erro detalhada e a causa original do erro.
+ *
+ * @param message A mensagem específica da exceção.
+ * @param cause A causa original do erro.
+ */
+ public UserEntityFailuresException(String message, Throwable cause) {
+ super(ERROR.formatErrorMessage(message), cause);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressEntityMapper.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressEntityMapper.java
new file mode 100644
index 0000000..c2fd896
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressEntityMapper.java
@@ -0,0 +1,42 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.AddressEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.AddressEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+
+/**
+ * Implementação da interface {@link MapperStrategy} para mapear um objeto {@link Address} para sua correspondente entidade {@link AddressEntity}.
+ * Esta classe é utilizada para converter um objeto {@link Address}, que representa um endereço no sistema, em um objeto {@link AddressEntity}
+ * que pode ser armazenado no banco de dados na tabela "address".
+ *
+ * Enquanto essa classe é específica para o mapeamento de objetos de endereço, ela implementa a interface {@link MapperStrategy},
+ * permitindo que seja usada em um contexto mais amplo de mapeamento de objetos.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class AddressEntityMapper implements MapperStrategy {
+
+ /**
+ * O {@code Class} do objeto de endereço, usado para formatar as mensagens de erro.
+ */
+ public static final Class ADDRESS_CLASS = Address.class;
+
+ /**
+ * Implementa o mapeamento de um objeto {@link Address} para um objeto {@link AddressEntity}.
+ * Inicialmente valida o objeto de origem não é nulo e por fim emprega um {@link BuilderMapper} para realizar a operação de mapeamento.
+ *
+ * @param source O objeto de origem que será convertido em um objeto de destino.
+ * @return Uma nova instância do {@link AddressEntity} com valores mapeados do objeto {@link Address}.
+ * @throws AddressEntityFailuresException Se a origem estiver nula ou vazia.
+ */
+ @Override
+ public AddressEntity mapFrom(Address source) {
+ ValidationUtils.validateNotNullOrEmpty(source, MapperFailureException.ERROR.formatErrorMessage(ADDRESS_CLASS.getSimpleName()), AddressEntityFailuresException.class);
+ return BuilderMapper.mapTo(AddressEntity.class, source);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressMapper.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressMapper.java
new file mode 100644
index 0000000..2e9bd0c
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressMapper.java
@@ -0,0 +1,53 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.AddressEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.AddressEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import diegosneves.github.conectardoacoes.core.exception.AddressCreationFailureException;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+
+/**
+ * A classe {@link AddressMapper} implementa a interface de estratégia de Mapeamento {@link MapperStrategy}
+ * para converter objetos {@link AddressEntity} em objetos {@link Address}.
+ *
+ * Esta classe é responsável por mapear uma entidade {@link AddressEntity} que representa um registro de endereço
+ * no banco de dados para um objeto {@link Address} usado no nível de aplicativo.
+ *
+ * Esta classe também valida os dados da {@link AddressEntity} e lança uma exceção
+ * {@link AddressEntityFailuresException} caso seja fornecida uma {@link AddressEntity} inválida.
+ *
+ * Contém uma mensgem erro predefinida para entidades de endereço inválidas: "Deve ser fornecida uma entidade de Endereço que seja válida."
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class AddressMapper implements MapperStrategy
{
+
+
+ public static final Class ADDRESS_ENTITY_TYPE = AddressEntity.class;
+
+ /**
+ * Realiza a conversão de um objeto {@link AddressEntity} para um objeto {@link Address}.
+ *
+ * Este método utiliza a biblioteca de utilidades de validação para verificar a entidade de endereço.
+ *
+ * Em caso de falha na criação da instância de {@link Address}, um {@link AddressCreationFailureException} é lançado
+ * e a exceção é reenviada pela {@link AddressEntityFailuresException} para sinalizar o erro de mapeamento.
+ *
+ * @param source O objeto {@link AddressEntity} fornecido que deve ser mapeado para um objeto {@link Address}.
+ * @return Retorna um novo objeto {@link Address} com todos os campos preenchidos com dados oriundos do {@link AddressEntity}.
+ * @throws AddressEntityFailuresException Se a entidade do endereço fornecida for nula ou inválida.
+ */
+ @Override
+ public Address mapFrom(AddressEntity source) {
+ ValidationUtils.validateNotNullOrEmpty(source, MapperFailureException.ERROR.formatErrorMessage(ADDRESS_ENTITY_TYPE.getSimpleName()), AddressEntityFailuresException.class);
+ Address address;
+ try {
+ address = new Address(source.getId(), source.getStreet(), source.getNumber(), source.getNeighborhood(), source.getCity(), source.getState(), source.getZip());
+ } catch (AddressCreationFailureException e) {
+ throw new AddressEntityFailuresException(MapperFailureException.ERROR.formatErrorMessage(ADDRESS_ENTITY_TYPE.getSimpleName()), e);
+ }
+ return address;
+ }
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/BuilderMapper.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/BuilderMapper.java
new file mode 100644
index 0000000..0b81b0a
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/BuilderMapper.java
@@ -0,0 +1,142 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ConstructorDefaultUndefinedException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+import lombok.extern.slf4j.Slf4j;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+
+/**
+ * A classe {@link BuilderMapper} fornece métodos para mapear os campos de um objeto fonte
+ * para os campos de uma classe destino.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+@Slf4j
+public class BuilderMapper {
+
+ public static final String SOURCE_OBJECT_NULL_ERROR_MESSAGE = "O objeto que está sendo mapeado não deve ser nulo. Verifique se o objeto foi corretamente inicializado.";
+ public static final String STRATEGY_CANNOT_BE_NULL = "O objeto MapperStrategy não pode ser nulo";
+
+ private BuilderMapper() {
+ }
+
+ /**
+ * Mapeia os campos do objeto de origem para os campos da classe de destino.
+ *
+ * @param o tipo da classe de destino
+ * @param destinationClass a classe a ser mapeada
+ * @param source o objeto de origem que será convertido no objeto de destino
+ * @return uma instância da classe de destino com seus campos preenchidos
+ * @throws ConstructorDefaultUndefinedException se a classe de destino não tiver um construtor padrão
+ * @throws MapperFailureException se ocorrer um erro ao mapear os campos
+ */
+ public static T mapTo(Class destinationClass, Object source) throws ConstructorDefaultUndefinedException, MapperFailureException {
+
+ var destinationFields = destinationClass.getDeclaredFields();
+
+ T mappedInstance = null;
+
+ try {
+ Constructor>[] constructors = destinationClass.getConstructors();
+ Constructor> defaultConstructor = null;
+ for (Constructor> constructor : constructors) {
+ if (constructor.getParameterCount() == 0) {
+ defaultConstructor = constructor;
+ break;
+ }
+ }
+ if (defaultConstructor != null) {
+ mappedInstance = (T) defaultConstructor.newInstance();
+ } else if (constructors.length > 0) {
+ Constructor> nextConstructor = constructors[0];
+
+ var params = nextConstructor.getParameters();
+ Object[] paramValues = new Object[params.length];
+
+ for (int i = 0; i < params.length; i++) {
+ Field field = findFieldWithName(source, params[i].getName(), params[i].getType());
+ if (field == null) {
+ continue;
+ }
+ field.setAccessible(true);
+ paramValues[i] = field.get(source);
+ }
+ mappedInstance = (T) nextConstructor.newInstance(paramValues);
+
+ } else {
+ log.error(ConstructorDefaultUndefinedException.ERROR.formatErrorMessage(destinationClass.getName()));
+ throw new ConstructorDefaultUndefinedException(destinationClass.getName());
+ }
+
+ } catch (Exception e) {
+ log.error(MapperFailureException.ERROR.formatErrorMessage(destinationClass.getName()), e);
+ throw new MapperFailureException(destinationClass.getName(), e);
+ }
+
+ for (Field field : destinationFields) {
+ field.setAccessible(true);
+ try {
+ var sourceField = source.getClass().getDeclaredField(field.getName());
+ sourceField.setAccessible(true);
+ field.set(mappedInstance, sourceField.get(source));
+ } catch (Exception ignored) {
+ }
+ }
+
+ return mappedInstance;
+ }
+
+ /**
+ * Método utilitário privado para encontrar e retornar um objeto {@link Field} de nome específico de uma instância de objeto fornecida (source).
+ * O objeto {@link Field} retornado é aquele cujo nome corresponde ao parâmetro de nome fornecido e é do tipo atribuível ao parâmetro de tipo fornecido (paramType).
+ *
+ * @param source A instância de objeto cujo campo está sendo procurado.
+ * @param name O nome do campo que está sendo procurado.
+ * @param paramType O tipo de classe do campo que está sendo procurado.
+ * @return Retorna um objeto Field se um campo correspondente for encontrado. Retorna null se nenhum campo correspondente for encontrado.
+ */
+ private static Field findFieldWithName(Object source, String name, Class> paramType) {
+ for (Field field : source.getClass().getDeclaredFields()) {
+ if (field.getName().equalsIgnoreCase(name)) {
+ if (!field.getType().isAssignableFrom(paramType)) {
+ continue;
+ }
+ return field;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Esta é uma função auxiliar genérica para converter (mapear) um objeto de origem em um destino desejado,
+ * usando uma estratégia de mapeamento fornecida. Ele fornece utilidade na redução de código duplicado ao
+ * lidar com conversões de objetos em projetos. A função utiliza Generics para manter a flexibilidade,
+ * permitindo que qualquer objeto seja mapeado para qualquer outro.
+ *
+ * Esta função verifica primeiro se a estratégia fornecida e o objeto de origem não são nulos.
+ * Se algum deles for nulo, a função lançará uma exceção {@link IllegalArgumentException}.
+ *
+ * O propósito deste método é fornecer um mapeamento eficaz de objetos e garantir a validade dos dados a serem mapeados.
+ *
+ * @param O tipo do objeto de destino, para o qual o objeto de origem será mapeado.
+ * @param O tipo do objeto de origem que será mapeado para o objeto de destino.
+ * @param strategy A estratégia de mapeamento que define a lógica de como o objeto de origem deve ser mapeado para o objeto de destino.
+ * Os detalhes sobre como implementar a estratégia são responsabilidade do desenvolvedor.
+ * @param source O objeto de origem a ser mapeado. A estrutura desse objeto depende do objeto definido durante a invocação.
+ * @return Retorna um novo objeto do tipo de destino (T) com seus campos mapeados do objeto de origem.
+ * @throws IllegalArgumentException será lançada se a estratégia de mapeamento ou o objeto de origem for null.
+ *
+ * @see MapperStrategy
+ * @see ValidationUtils
+ */
+ public static T mapTo(MapperStrategy strategy, E source) {
+ ValidationUtils.validateNotNullOrEmpty(strategy, STRATEGY_CANNOT_BE_NULL, IllegalArgumentException.class);
+ ValidationUtils.validateNotNullOrEmpty(source, SOURCE_OBJECT_NULL_ERROR_MESSAGE, IllegalArgumentException.class);
+ return strategy.mapFrom(source);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationEntityMapper.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationEntityMapper.java
new file mode 100644
index 0000000..3bcd901
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationEntityMapper.java
@@ -0,0 +1,41 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.DonationEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+
+/**
+ * Classe responsável por implementar a estratégia de mapeamento para objetos {@link Donation}
+ * para objetos {@link DonationEntity}.
+ * Essa classe permite a conversão de instâncias de {@link Donation} em objetos {@link DonationEntity}, que
+ * podem ser persistidos no banco de dados.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class DonationEntityMapper implements MapperStrategy {
+
+ public static final Class DONATION_CLASS = Donation.class;
+
+ /**
+ * Mapeia o objeto {@link Donation} fornecido para um objeto {@link DonationEntity}.
+ *
+ * Este método recebe um objeto {@link Donation}, valida se o objeto não é nulo através do utilitário {@link ValidationUtils},
+ * e em seguida, usa o mapeador {@link BuilderMapper} para mapear o objeto {@link Donation} para um objeto {@link DonationEntity}.
+ *
+ * @param source o objeto {@link Donation} a ser mapeado
+ * @return um objeto {@link DonationEntity} que representa a entidade de doação
+ * @throws ShelterEntityFailuresException se o objeto {@link Donation} fornecido for nulo
+ * @throws MapperFailureException se ocorrer um erro durante o mapeamento
+ */
+ @Override
+ public DonationEntity mapFrom(Donation source) {
+ ValidationUtils.validateNotNullOrEmpty(
+ source,
+ MapperFailureException.ERROR.formatErrorMessage(DONATION_CLASS.getSimpleName()),
+ ShelterEntityFailuresException.class);
+ return BuilderMapper.mapTo(DonationEntity.class, source);
+ }
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationMapper.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationMapper.java
new file mode 100644
index 0000000..b147058
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationMapper.java
@@ -0,0 +1,62 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.DonationEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.exception.DonationRegisterFailureException;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+
+/**
+ * Esta classe implementa a interface {@link MapperStrategy} para mapear a entidade {@link DonationEntity} para o objeto de domínio {@link Donation}.
+ * É confiável para a conversão de uma entidade do banco de dados para o objeto do domínio.
+ *
+ *
A classe usa a estratégia definida pela interface MapperStrategy
+ * para converter um {@link DonationEntity} para um objeto de domínio doação.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ * @see Donation
+ * @see DonationEntity
+ * @see MapperStrategy
+ */
+public class DonationMapper implements MapperStrategy {
+
+ /**
+ * Mapeia a entidade de doação do banco de dados para uma instância do objeto de domínio doação.
+ *
+ * O método aceita uma entidade {@link DonationEntity} como input e cria uma nova instância do domínio de doação com base nesse input.
+ * O mapeamento é feito da seguinte maneira:
+ *
+ * A entidade passada é primeiramente validada para verificar se não é nula. Se a entidade for nula, uma exceção
+ * {@link ShelterEntityFailuresException} é lançada com uma mensagem de erro formatada.
+ *
+ * Em seguida, uma tentativa é feita para criar uma nova instância do domínio de doação, usando os valores retornados
+ * pelos métodos {@code getId()}, {@code getDescription()} e {@code getAmount()} da entidade {@link DonationEntity}.
+ *
+ * Se a tentativa falhar por algum motivo (por exemplo, se os valores retornados não passarem nas verificações de
+ * validação no construtor do domínio de doação), uma {@link DonationRegisterFailureException} é capturada e uma {@link ShelterEntityFailuresException}
+ * é lançada com uma mensagem de erro formatada e a exceção original anexada.
+ *
+ * Se a criação da nova instância de Doação for bem-sucedida, essa instância é retornada.
+ *
+ * @param source o objeto {@link DonationEntity} que será mapeado para o objeto de domínio doação. Não deve ser nulo.
+ * @return uma nova instância do domínio doação, mapeada dos campos de uma entidade {@link DonationEntity}.
+ * @throws ShelterEntityFailuresException se a entidade de entrada for nula ou se houver uma falha durante a criação da nova instância de Doação.
+ */
+ @Override
+ public Donation mapFrom(DonationEntity source) {
+ ValidationUtils.validateNotNullOrEmpty(
+ source,
+ MapperFailureException.ERROR.formatErrorMessage(DonationEntity.class.getSimpleName()),
+ ShelterEntityFailuresException.class);
+
+ Donation donation = null;
+ try {
+ donation = new Donation(source.getId(), source.getDescription(), source.getAmount());
+ } catch (DonationRegisterFailureException e) {
+ throw new ShelterEntityFailuresException(MapperFailureException.ERROR.formatErrorMessage(DonationEntity.class.getSimpleName()), e);
+ }
+ return donation;
+ }
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/MapperStrategy.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/MapperStrategy.java
new file mode 100644
index 0000000..7b7011c
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/MapperStrategy.java
@@ -0,0 +1,22 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+/**
+ * A interface {@link MapperStrategy} define uma estratégia para executar operações de mapeamento de objetos.
+ *
+ * @author diegosneves
+ * @since 1.0.0
+ *
+ * @param o tipo da classe de destino
+ * @param o tipo do objeto de origem
+ */
+public interface MapperStrategy {
+
+ /**
+ * Executa a estratégia para realizar uma operação de mapeamento entre objetos.
+ *
+ * @param source o objeto de source que será convertido no objeto de destino
+ * @return uma instância da classe de destino com seus campos preenchidos
+ */
+ T mapFrom(E source);
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterEntityMapper.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterEntityMapper.java
new file mode 100644
index 0000000..892a2fe
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterEntityMapper.java
@@ -0,0 +1,85 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.AddressEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.DonationEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.ShelterEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.ShelterContract;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Classe {@link ShelterEntityMapper} que implementa a interface {@link MapperStrategy} para executar operações de mapeamento entre a classe {@link ShelterContract} e a classe {@link ShelterEntity}.
+ *
+ * Esta classe contém métodos que realizam o mapeamento de um objeto {@link ShelterContract} para um objeto {@link ShelterEntity}.
+ *
+ * Esta classe usa a classes {@link AddressEntityMapper}, {@link UserEntityMapper} e {@link DonationEntityMapper} para mapear respectivas partes do objeto {@link ShelterContract}.
+ *
+ * Também contém um método auxiliar para mapear uma lista de objetos {@link Donation}.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class ShelterEntityMapper implements MapperStrategy {
+
+ public static final Class SHELTER_CLASS = ShelterContract.class;
+
+ /**
+ * Método que converte a fonte, um objeto da classe {@link ShelterContract}, para um novo objeto da classe {@link ShelterEntity}.
+ *
+ * O objeto de origem é verificado para não ser nulo ou vazio, caso contrário, uma {@link ShelterEntityFailuresException} é lançada.
+ * Cada campo do objeto de origem é mapeado para um campo correspondente no objeto de destino. Os objetos {@link Address} e {@link UserContract} do objeto de origem são convertidos em {@link AddressEntity} e {@link UserEntity}, respectivamente, através dos mappers apropriados.
+ * As doações em {@link ShelterContract} são mapeadas para {@link DonationEntity} usando o método {@code getDonationEntities}.
+ *
+ * Se ocorrer uma exceção durante o processo de mapeamento, uma {@link ShelterEntityFailuresException} é lançada, encapsulando a exceção original.
+ *
+ * @param source objeto {@link ShelterContract} que deve ser mapeado
+ * @return um novo objeto {@link ShelterEntity} que é o resultado do mapeamento.
+ * @throws ShelterEntityFailuresException se a fonte {@link ShelterContract} for {@code null} ou vazia, ou se ocorrer um erro ao mapear qualquer um dos campos.
+ */
+ @Override
+ public ShelterEntity mapFrom(ShelterContract source) {
+ ValidationUtils.validateNotNullOrEmpty(source, MapperFailureException.ERROR.formatErrorMessage(SHELTER_CLASS.getSimpleName()), ShelterEntityFailuresException.class);
+ ShelterEntity shelterEntity = null;
+
+ try {
+ shelterEntity = ShelterEntity.builder()
+ .id(source.getId())
+ .shelterName(source.getShelterName())
+ .address(new AddressEntityMapper().mapFrom(source.getAddress()))
+ .responsibleUser(new UserEntityMapper().mapFrom((User) source.getUser()))
+ .donations(getDonationEntities(source.getDonations()))
+ .build();
+ } catch (RuntimeException e) {
+ throw new ShelterEntityFailuresException(MapperFailureException.ERROR.formatErrorMessage(SHELTER_CLASS.getSimpleName()), e);
+ }
+ return shelterEntity;
+ }
+
+ /**
+ * Método que converte a lista de doações da classe {@link Donation} em uma lista de objetos {@link DonationEntity}.
+ *
+ * Esse método recebe como parâmetro uma lista de objetos {@link Donation} e, usando a classe {@link DonationEntityMapper}, transforma cada objeto {@link Donation} em um objeto {@link DonationEntity}, retornando uma lista completa desses objetos.
+ *
+ * Se a lista fornecida for nula ou vazia, o método retornará uma nova lista vazia.
+ *
+ * @param list uma lista de objetos {@link Donation} que deve ser convertida
+ * @return uma lista de objetos {@link DonationEntity} resultante da conversão. Se a lista fornecida for nula ou vazia, retorna uma nova lista vazia.
+ */
+ private static List getDonationEntities(List list) {
+ if (list == null || list.isEmpty()) {
+ return new ArrayList<>();
+ }
+ return list.stream().map(new DonationEntityMapper()::mapFrom).toList();
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterMapper.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterMapper.java
new file mode 100644
index 0000000..82c55cd
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterMapper.java
@@ -0,0 +1,103 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.DonationEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.ShelterEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.ShelterContract;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.exception.DonationRegisterFailureException;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+
+/**
+ * Implementação da interface {@link MapperStrategy} para a conversão entre a entidade {@link ShelterEntity} e a classe de domínio {@link ShelterContract}.
+ * Fornece funcionalidades para mapear um objeto {@link ShelterEntity} em um objeto {@link ShelterContract}.
+ * Utiliza a classe {@link UserMapper} para mapear o usuário responsável ({@link UserEntity}) para um objeto {@link User}.
+ *
+ * @author diegoneves
+ * @see MapperStrategy
+ * @since 1.0.0
+ */
+public class ShelterMapper implements MapperStrategy {
+
+ public static final Class SHELTER_ENTITY_CLASS = ShelterEntity.class;
+
+
+ /**
+ * Este método converte um objeto {@link ShelterEntity} em um novo objeto {@link ShelterContract}.
+ *
+ * Primeiramente, verifica se a entidade fornecida não é nula.
+ * Se for, lança uma {@link ShelterEntityFailuresException} com uma mensagem de erro formatada.
+ *
+ * Em seguida, tenta instanciar um novo objeto {@link ShelterContract} passando os atributos necessários do objeto de entidade.
+ * Para o mapeamento de {@link Address} e {@link User}, delega a operação de mapeamento para duas instâncias diferentes, {@link AddressMapper} e {@link UserMapper}.
+ *
+ * Se tudo ocorrer bem, o {@link Shelter} construído tem os mesmos valores de atributos que o da entidade.
+ * Se uma {@link RuntimeException} for lançada durante a operação de instanciação, ela é capturada e uma nova {@link ShelterEntityFailuresException}
+ * é lançada com uma mensagem de erro formatada e a exceção capturada é passada para essa nova exceção.
+ *
+ * Por último, o método {@link #mappedDonationsToShelter} é chamado para mapear as doações relacionadas para o novo {@link ShelterContract} construído
+ * e então o {@link ShelterContract} é retornado.
+ *
+ *
+ * @param source O objeto {@link ShelterEntity} que precisa ser convertido em um objeto {@link Shelter}.
+ * @return Um objeto {@link Shelter} que foi criado a partir do {@link ShelterEntity}.
+ * @throws ShelterEntityFailuresException Se ocorrer um erro durante a operação de mapeamento de um {@link ShelterEntity} para um {@link Shelter}.
+ * @see diegosneves.github.conectardoacoes.adapters.rest.mapper.MapperStrategy#mapFrom
+ * @see diegosneves.github.conectardoacoes.adapters.rest.mapper.ShelterMapper#mappedDonationsToShelter
+ * @see diegosneves.github.conectardoacoes.adapters.rest.mapper.AddressMapper#mapFrom
+ * @see diegosneves.github.conectardoacoes.adapters.rest.mapper.UserMapper#mapFrom
+ */
+ @Override
+ public ShelterContract mapFrom(ShelterEntity source) {
+ ValidationUtils.validateNotNullOrEmpty(source, MapperFailureException.ERROR.formatErrorMessage(SHELTER_ENTITY_CLASS.getSimpleName()), ShelterEntityFailuresException.class);
+
+ Shelter constructedShelter = null;
+ try {
+ constructedShelter = new Shelter(
+ source.getId(),
+ source.getShelterName(),
+ new AddressMapper().mapFrom(source.getAddress()),
+ new UserMapper().mapFrom(source.getResponsibleUser()));
+ } catch (RuntimeException e) {
+ throw new ShelterEntityFailuresException(MapperFailureException.ERROR.formatErrorMessage(SHELTER_ENTITY_CLASS.getSimpleName()), e);
+ }
+ this.mappedDonationsToShelter(source, constructedShelter);
+ return constructedShelter;
+ }
+
+
+ /**
+ * Mapeia as doações de uma entidade de abrigo {@link ShelterEntity} para um abrigo construído {@link ShelterContract}.
+ *
+ * Este método privado é usado quando um objeto {@link ShelterContract} está sendo construído a partir de um objeto {@link ShelterEntity}.
+ * Sua tarefa principal é garantir que todas as doações associadas à entidade de abrigo sejam devidamente mapeadas e atribuídas ao novo objeto Shelter.
+ *
+ *
+ * O método funciona da seguinte maneira:
+ *
+ * - Verifica se há doações associadas à entidade de abrigo. Se não houver, o método retorna imediatamente e nenhuma doação é adicionada ao abrigo.
+ * - Se houver doações, o método percorre a lista de doações na entidade. Para cada {@link DonationEntity} na lista, ele cria um novo objeto {@link Donation} com a descrição e o valor da entidade da doação.
+ * - Esse novo objeto de Doação é adicionado ao objeto de abrigo construído por meio do método addDonation.
+ *
+ * @param shelterEntity A entidade de abrigo de onde as doações serão extraídas. Este é um objeto {@link ShelterEntity} cujas doações estão sendo mapeadas.
+ * @param constructedShelter O objeto Shelter que está sendo construído. As doações extraídas da entidade de abrigo serão atribuídas a este objeto.
+ * @throws ShelterEntityFailuresException Se uma falha ocorrer durante a operação de adicionar a doação ao abrigo ou durante o registro da doação.
+ */
+ private void mappedDonationsToShelter(ShelterEntity shelterEntity, ShelterContract constructedShelter) throws ShelterEntityFailuresException {
+ if (shelterEntity.getDonations().isEmpty()) {
+ return;
+ }
+ for (DonationEntity donationEntity : shelterEntity.getDonations()) {
+ try {
+ constructedShelter.addDonation(new Donation(donationEntity.getId(), donationEntity.getDescription(), donationEntity.getAmount()));
+ } catch (DonationRegisterFailureException e) {
+ throw new ShelterEntityFailuresException(MapperFailureException.ERROR.formatErrorMessage(Donation.class.getSimpleName()), e);
+ }
+ }
+ }
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserEntityMapper.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserEntityMapper.java
new file mode 100644
index 0000000..fa39004
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserEntityMapper.java
@@ -0,0 +1,57 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+
+/**
+ * A classe {@code UserEntityMapper} implementa a interface {@link MapperStrategy} e é usada para mapear um objeto do tipo {@link User} para um objeto de entidade {@link UserEntity}.
+ *
+ * Essa classe é essencial para a camada de persistência do aplicativo, pois permite uma conversão eficiente entre objetos do domínio do problema e entidades que podem ser persistidas em um banco de dados.
+ *
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class UserEntityMapper implements MapperStrategy {
+
+ public static final Class USER_CLASS = UserContract.class;
+
+ /**
+ * Este método é usado para mapear um objeto de origem do tipo {@link User} para um objeto de entidade {@link UserEntity}.
+ *
+ * Primeiro, realiza uma verificação de not-null-or-empty do objeto de origem utilizando a utilidade {@link ValidationUtils}.
+ * Se o objeto de origem for nulo ou vazio, um {@link UserEntityFailuresException} será lançado com a mensagem de erro gerada por {@link MapperFailureException#ERROR}.
+ *
+ *
+ * Em seguida, tenta mapear o objeto de origem para a classe {@link UserEntity} usando a utilidade {@link BuilderMapper}.
+ * Após o mapeamento bem-sucedido, ele então tenta configurar o perfil do usuário no objeto de entidade mapeado. O perfil do usuário é obtido a partir do perfil do usuário do objeto de origem e convertido para uma enumeração de {@link UserProfileType}.
+ *
+ *
+ * Se um {@link RuntimeException} é lançado durante o mapeamento ou a configuração do perfil do usuário, um novo {@link UserEntityFailuresException} é lançado com a mensagem de erro gerada por {@link MapperFailureException#ERROR} e a exceção original anexada para fins de rastreamento.
+ *
+ * O objeto {@link UserEntity} mapeado, ou nulo se não foi possível realizar o mapeamento, é retornado ao chamador.
+ *
+ * @param source o objeto do tipo {@link User} que é usado como base para criar um objeto de entidade {@link UserEntity}.
+ * @return um objeto {@link UserEntity} mapeado a partir do objeto de origem do tipo {@link User},
+ * ou nulo se o mapeamento não foi possível devido a exceções durante o mapeamento ou a configuração do perfil do usuário da entidade.
+ * @throws UserEntityFailuresException se o objeto de origem é nulo ou vazio, ou se um erro ocorrer durante o mapeamento ou a configuração do perfil do usuário.
+ */
+ @Override
+ public UserEntity mapFrom(UserContract source) {
+ ValidationUtils.validateNotNullOrEmpty(source, MapperFailureException.ERROR.formatErrorMessage(USER_CLASS.getSimpleName()), UserEntityFailuresException.class);
+ UserEntity userEntity = null;
+ try {
+ userEntity = BuilderMapper.mapTo(UserEntity.class, source);
+ userEntity.setUserProfile(Enum.valueOf(UserProfileType.class, source.getUserProfile().name()));
+ } catch (RuntimeException e) {
+ throw new UserEntityFailuresException(MapperFailureException.ERROR.formatErrorMessage(USER_CLASS.getSimpleName()), e);
+ }
+ return userEntity;
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserMapper.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserMapper.java
new file mode 100644
index 0000000..7aad399
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserMapper.java
@@ -0,0 +1,75 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import diegosneves.github.conectardoacoes.core.exception.UserCreationFailureException;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+
+/**
+ * Implementação da interface {@link MapperStrategy} para a conversão entre a entidade {@link UserEntity} e a classe de domínio {@link User}.
+ * Fornece funcionalidades para mapear um objeto {@link UserEntity} em um objeto {@link User}.
+ *
+ * A classe {@link UserMapper} tem a função de converter os dados de um objeto {@link UserEntity}, que são compatíveis com o modelo de
+ * dados do banco, para um objeto {@link User}, que é o modelo de negócio do sistema.
+ *
+ * Como é uma implementação da interface {@link MapperStrategy}, a classe {@link UserMapper} é obrigada a implementar o método {@code mapFrom}.
+ *
+ * @author diegoneves
+ * @see MapperStrategy
+ * @since 1.0.0
+ */
+public class UserMapper implements MapperStrategy {
+
+ public static final Class USER_ENTITY_CLASS = UserEntity.class;
+
+ /**
+ * Mapeia uma entidade de usuário ({@link UserEntity}) para um objeto de usuário de domínio ({@link User}).
+ * Realiza a conversão de uma entidade persistida de um usuário para uma representação de usuário de domínio.
+ *
+ * O mapeamento é realizado atribuindo cada campo do objeto {@link User} com os valores correspondentes do objeto {@link UserEntity}.
+ * Além disso, o perfil do usuário é obtido utilizando o método valueOf da classe Enum, que retornará o perfil
+ * correspondente de acordo com o nome do perfil informado.
+ *
+ * @param source a entidade de origem que representa um usuário no banco de dados
+ * @return uma instância da classe de domínio {@link User}, com seus campos preenchidos com os valores correspondentes da entidade de origem
+ */
+ @Override
+ public UserContract mapFrom(UserEntity source) {
+ this.validateData(source);
+ this.validateData(source.getUserProfile());
+ User mappedUser = null;
+ try {
+ mappedUser = new User(
+ source.getId(),
+ source.getUserName(),
+ source.getEmail(),
+ Enum.valueOf(UserProfile.class, source.getUserProfile().name()),
+ source.getUserPassword());
+ } catch (UserCreationFailureException e) {
+ throw new UserEntityFailuresException(MapperFailureException.ERROR.formatErrorMessage(USER_ENTITY_CLASS.getSimpleName()), e);
+ }
+ return mappedUser;
+ }
+
+ /**
+ * Este método é usado para verificar se o dado fornecido é nulo
+ * ou vazio (no caso de Strings) e lança uma exceção se alguma dessas condições for atendida.
+ * Este método é útil para validar os dados antes de operações que requerem que esses dados não sejam nulos ou vazios.
+ *
+ * @param o tipo de dado a ser validado. Como este é um método genérico, ele pode aceitar qualquer tipo de objeto.
+ * @param data o dado a ser validado.
+ * @throws UserEntityFailuresException se o dado fornecido for nulo ou, no caso de Strings, estiver vazio.
+ * A mensagem da exceção será uma mensagem de erro formatada a partir do {@link MapperFailureException#ERROR} anexada com a
+ * simplificação do nome da classe {@link UserEntity}.
+ * @see ValidationUtils
+ * @see MapperFailureException
+ */
+ private void validateData(T data) throws UserEntityFailuresException {
+ ValidationUtils.validateNotNullOrEmpty(data, MapperFailureException.ERROR.formatErrorMessage(USER_ENTITY_CLASS.getSimpleName()), UserEntityFailuresException.class);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/AddressEntity.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/AddressEntity.java
new file mode 100644
index 0000000..6b7feec
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/AddressEntity.java
@@ -0,0 +1,40 @@
+package diegosneves.github.conectardoacoes.adapters.rest.model;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Objeto de entidade {@link AddressEntity} que representa um objeto endereço no banco de dados mapeado para a tabela "address".
+ *
+ * Esta classe é uma entidade do JPA que representa a tabela "address".
+ *
+ * Anotado com Lombok, o que significa que os construtores, getters e setters são gerados automaticamente.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+@Entity
+@Table(name = "address")
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Getter
+@Setter
+public class AddressEntity {
+
+ @Id
+ private String id;
+ private String street;
+ private String number;
+ private String neighborhood;
+ private String city;
+ private String state;
+ private String zip;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/DonationEntity.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/DonationEntity.java
new file mode 100644
index 0000000..36ed32f
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/DonationEntity.java
@@ -0,0 +1,36 @@
+package diegosneves.github.conectardoacoes.adapters.rest.model;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Objeto de entidade {@link DonationEntity} que representa um objeto doação no banco de dados mapeado para a tabela "donations".
+ *
+ * Esta classe é uma entidade do JPA que representa a tabela "donations".
+ *
+ * Anotado com Lombok, o que significa que os construtores, getters e setters são gerados automaticamente.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+@Entity
+@Table(name = "donations")
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Getter
+@Setter
+public class DonationEntity {
+
+ @Id
+ private String id;
+ private String description;
+ private Integer amount;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/ShelterEntity.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/ShelterEntity.java
new file mode 100644
index 0000000..b1440f9
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/ShelterEntity.java
@@ -0,0 +1,45 @@
+package diegosneves.github.conectardoacoes.adapters.rest.model;
+
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.OneToMany;
+import jakarta.persistence.OneToOne;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.util.List;
+
+/**
+ * Objeto de entidade {@link ShelterEntity} que representa um objeto abrigo no banco de dados mapeado para a tabela "shelters".
+ *
+ * Esta classe é uma entidade do JPA que representa a tabela "shelters".
+ *
+ * Anotado com Lombok, o que significa que os construtores, getters e setters são gerados automaticamente.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+@Entity
+@Table(name = "shelters")
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Builder
+public class ShelterEntity {
+
+ @Id
+ private String id;
+ private String shelterName;
+ @OneToOne
+ private AddressEntity address;
+ @OneToOne
+ private UserEntity responsibleUser;
+ @OneToMany
+ private List donations;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/UserEntity.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/UserEntity.java
new file mode 100644
index 0000000..ae7bad0
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/model/UserEntity.java
@@ -0,0 +1,57 @@
+package diegosneves.github.conectardoacoes.adapters.rest.model;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Representa um usuário no sistema. Cada usuário tem um identificador único, nome de usuário,
+ * endereço de e-mail, perfil de usuário e senha.
+ *
+ * Anotações usadas na classe:
+ *
+ * - {@code @Entity} - Anotação do JPA que denota que esta é uma classe de entidade.
+ * - {@code @Table} - Anotação do JPA usada para especificar detalhes da tabela de banco de dados correspondente.
+ * - {@code @AllArgsConstructor} - Anotação do Lombok para gerar um construtor com um parâmetro para cada campo.
+ * - {@code @NoArgsConstructor} - Anotação do Lombok para gerar um construtor sem parâmetros.
+ * - {@code @Builder} - Anotação do Lombok para suportar o padrão Builder de design para a construção de objetos.
+ * - {@code @Getter} - Anotação do Lombok para gerar getters para todos os campos.
+ * - {@code @Setter} - Anotação do Lombok para gerar setters para todos os campos.
+ *
+ *
+ * Os atributos da classe incluem:
+ *
+ * - {@code userId} - O identificador único do usuário. Chave primária para a tabela do banco de dados.
+ * - {@code userName} - O nome de usuário escolhido pelo usuário. Deve ser único.
+ * - {@code email} - O endereço de email do usuário. Usado para comunicação e notificações.
+ * - {@code userProfile} - O perfil do usuário que determina suas permissões e acessos.
+ * - {@code userPassword} - A senha escolhida pelo usuário para acesso seguro ao sistema.
+ *
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ *
+ */
+@Entity
+@Table(name = "users")
+@AllArgsConstructor
+@NoArgsConstructor
+@Builder
+@Getter
+@Setter
+public class UserEntity {
+
+ @Id
+ private String id;
+ private String userName;
+ private String email;
+ private UserProfileType userProfile;
+ private String userPassword;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/AddressRepository.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/AddressRepository.java
new file mode 100644
index 0000000..438ea0b
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/AddressRepository.java
@@ -0,0 +1,34 @@
+package diegosneves.github.conectardoacoes.adapters.rest.repository;
+
+import diegosneves.github.conectardoacoes.adapters.rest.model.AddressEntity;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+/**
+ * Java Persistence API (JPA) Repository para {@link AddressEntity}.
+ * Esta interface estende {@link CrudRepository}, que fornece métodos como save(…), findOne(…), findAll(), count(), delete(…) etc.
+ *
+ * Aciona consultas de banco de dados relacionadas a {@link AddressEntity}.
+ *
+ * @Repository indica que esta interface é um Repositório Spring Data JPA, um mecanismo que fornece
+ * métodos de manipulação de dados comuns sem a necessidade de escrever nossa própria lógica de consulta.
+ * O Spring Data JPA também se integra bem ao Hibernate, uma implementação popular do padrão Java Persistence API.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+@Repository
+public interface AddressRepository extends CrudRepository {
+
+ /**
+ * Retorna um conteiner Optional encapsulando o {@link AddressEntity} encontrado pelo Id.
+ *
+ * @param id String, identificador da entidade de endereço a ser procurada. Deve ser não nulo.
+ * @return um Optional de {@link AddressEntity}. Este Optional será não nulo, mas pode estar vazio se nenhum AddressEntity
+ * com o ID fornecido for encontrado.
+ */
+ Optional findById(String id);
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/DonationRepository.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/DonationRepository.java
new file mode 100644
index 0000000..35a34a0
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/DonationRepository.java
@@ -0,0 +1,44 @@
+package diegosneves.github.conectardoacoes.adapters.rest.repository;
+
+import diegosneves.github.conectardoacoes.adapters.rest.model.DonationEntity;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.Optional;
+
+/**
+ * Definição da interface do repositório para a entidade de doação {@link DonationEntity}.
+ * Esta interface estende a interface CrudRepository do Spring Data JPA,
+ * o que torna disponível metódos básicos de CRUD (Create, Read, Update, Delete).
+ *
+ * Esta interface define um método personalizado para buscar uma entidade de doação com base no ID.
+ *
+ * @Repository - Esta anotação é uma especialização da anotação @Component, permitindo detecção automática de classes.
+ * Isso também traduzirá qualquer exceção de tempo de execução lançada por classes de repositório,
+ * back-end de dados ou suporte de persistência para a exceção específica do Spring {@link org.springframework.dao.DataAccessException}.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ * @see org.springframework.data.repository.CrudRepository
+ */
+@Repository
+public interface DonationRepository extends CrudRepository {
+
+ /**
+ * Este método é usado para encontrar uma entidade de doação com base no ID.
+ *
+ * @param id - O ID da entidade de doação que está sendo procurada.
+ * Este parâmetro é usado para identificar a entidade de doação a ser buscada.
+ * @return Retorna um {@link Optional} que pode ou não conter uma entidade de doação, dependendo se um
+ * correspondente foi encontrado ou não.
+ * Optional é usado aqui para forçar o programador a pensar
+ * sobre o caso em que a entidade de doação pode não ser encontrada.
+ * Isso reduz o risco de lançar um NullPointerException não intencional.
+ * Se uma entidade de doação correspondente for encontrada, ela será retornada, caso contrário,
+ * um Optional vazio será retornado.
+ *
+ * @throws org.springframework.dao.DataAccessException - em caso de falha na persistência.
+ */
+ Optional findById(String id);
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/ShelterRepository.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/ShelterRepository.java
new file mode 100644
index 0000000..9cb5fd5
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/ShelterRepository.java
@@ -0,0 +1,204 @@
+package diegosneves.github.conectardoacoes.adapters.rest.repository;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.BuilderMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.MapperStrategy;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.ShelterEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.ShelterMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.model.ShelterEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.ShelterContract;
+import diegosneves.github.conectardoacoes.core.domain.shelter.shared.repository.ShelterContractRepository;
+import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;
+import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
+import diegosneves.github.conectardoacoes.core.utils.UuidUtils;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Este repositório é responsável pela persistência de dados relacionados a abrigos ({@link Shelter}).
+ *
+ * Faz uso de interfaces do Spring Data JPA para implementação do CRUD (Criação, Leitura, Atualização e Deleção) padrão, além de
+ * herdar de um contrato específico do Shelter para implementar suas próprias operações básicas (Encontrar por ID, Buscar todas,
+ * Persistir e Deletar por ID).
+ *
+ * Mecanismos de mapeamento são usados para desacoplar a conversão entre entidades JPA e objetos de domínio.
+ *
+ * @author diegoneves
+ * @see ShelterContractRepository
+ * @see CrudRepository
+ * @since 1.0.0
+ */
+@Repository
+public interface ShelterRepository extends ShelterContractRepository, CrudRepository {
+
+
+ String INVALID_ID_MESSAGE = "Deve ser fornecido um ID válido!";
+ String SHELTER_ERROR_MESSAGE = "Um objeto Abrigo válido deve ser fornecido para persistência!";
+
+ /**
+ * Retorna uma nova instância do {@link MapperStrategy} para mapear uma entidade {@link ShelterEntity} para a classe de domínio {@link Shelter}.
+ * O {@link MapperStrategy} é uma estratégia de design que desacopla a conversão de objeto para objeto para uma complexidade reduzida e manutenção mais fácil.
+ *
+ * @return uma nova instância de {@link ShelterMapper} que implementa a interface {@link MapperStrategy}
+ */
+ private ShelterMapper getShelterMapper() {
+ return new ShelterMapper();
+ }
+
+ /**
+ * Valida o valor de ID (identificador) fornecido. A validação ocorre em duas etapas:
+ * 1. Verifica se o ID fornecido não é nulo e nem vazio, lançando uma exceção do tipo {@link ShelterEntityFailuresException}
+ * com uma mensagem de erro correspondente se a validação falhar.
+ * 2. Verifica se o ID fornecido é um UUID válido, lançando uma exceção do tipo {@link ShelterEntityFailuresException}
+ * com a causa original da falha se a validação falhar.
+ * Note que este método é privado e deve ser usado apenas dentro da interface {@link ShelterRepository}.
+ *
+ * @param id O ID que será validado. Deve ser uma string não nula e não vazia representando um UUID válido.
+ * @throws ShelterEntityFailuresException se o ID fornecido for nulo, vazio ou não for um UUID válido.
+ * @see ValidationUtils#validateNotNullOrEmpty(Object, String, Class)
+ * @see UuidUtils#isValidUUID(String)
+ */
+ private void validateId(String id) throws ShelterEntityFailuresException {
+ ValidationUtils.validateNotNullOrEmpty(id, INVALID_ID_MESSAGE, ShelterEntityFailuresException.class);
+ try {
+ UuidUtils.isValidUUID(id);
+ } catch (UuidUtilsException e) {
+ throw new ShelterEntityFailuresException(INVALID_ID_MESSAGE, e);
+ }
+ }
+
+ /**
+ * Recebe uma lista de entidades {@link ShelterEntity}, realiza o mapeamento das instâncias de {@link ShelterEntity} para {@link Shelter} e retorna uma lista de Shelters.
+ * Este método é particularmente útil na conversão de entidades do banco de dados para objetos de domínio, para uso em outras partes da aplicação.
+ *
+ * @param entities Uma lista de instâncias de {@link ShelterEntity} que se pretende mapear para instâncias de {@link Shelter}
+ * @return Uma lista de instâncias de {@link ShelterContract} obtidas a partir do mapeamento das entidades recebidas. Se a lista de entrada for vazia, o método irá retornar uma lista vazia.
+ * @see MapperStrategy
+ * @see ShelterEntity
+ * @see Shelter
+ */
+ private List mapEntityList(List entities) {
+ if (entities == null || entities.isEmpty()) {
+ return Collections.emptyList();
+ }
+ return entities.stream().map(this.getShelterMapper()::mapFrom).toList();
+ }
+
+ /**
+ * Este método é usado para encontrar e retornar uma entidade {@link ShelterEntity} pelo ID.
+ *
+ * Primeiro, é executada a função findById do Repositório do Spring, que retorna um {@link Optional} de {@link ShelterEntity}.
+ * Então verifica-se se o {@link Optional} está vazio. Se estiver vazio, significa que nenhuma entidade foi encontrada com o ID fornecido, e o método retorna {@code null}.
+ * Se o {@link Optional} não estiver vazio, o método tenta mapear a {@link ShelterEntity} encontrada para uma instância de {@link ShelterContract}.
+ *
+ * Uma {@link ShelterCreationFailureException} pode ser lançada durante o mapeamento. Se isso acontecer, o método lança uma nova {@link ShelterEntityFailuresException} com uma mensagem de erro adequada.
+ *
+ * @param id A String que representa o ID único da entidade {@link ShelterEntity} a ser encontrada. Deve ser um valor não nulo e não vazio.
+ * @return Uma instância de {@link ShelterContract} que representa a entidade {@link Shelter} mapeada da {@link ShelterEntity} encontrada. Se nenhuma entidade for encontrada com o id fornecido, o método retornará null.
+ * @throws ShelterEntityFailuresException se ocorrer uma exceção {@link ShelterCreationFailureException} durante o mapeamento da entidade {@link ShelterEntity} para a instância de {@link ShelterContract}.
+ */
+ @Override
+ default ShelterContract findEntityById(String id) {
+ ShelterEntity entityToMap = this.getShelterEntityById(id);
+ if (entityToMap == null) return null;
+ return this.getShelterMapper().mapFrom(entityToMap);
+ }
+
+ /**
+ * Este método privado tem como objetivo recuperar um objeto {@link ShelterEntity} com base no id fornecido.
+ * Ele faz isso primeiro validando o id fornecido usando o método {@code validateId(String id)}.
+ * A validação garante que o id não seja nulo nem vazio e que seja um UUID válido.
+ * Caso contrário, uma exceção {@link ShelterEntityFailuresException} é lançada.
+ *
+ * Após a validação bem-sucedida do id, o método {@code findById(String id)} é chamado
+ * para obter o {@link Optional} de {@link ShelterEntity} correspondente ao id fornecido.
+ *
+ * Se o {@link Optional} estiver presente, o valor é retornado. Caso contrário, {@code null} é retornado.
+ *
+ * @param id A string que representa o UUID da entidade {@link ShelterEntity} a ser recuperada.
+ * Deve ser um UUID válido. Caso contrário, uma exceção {@link ShelterEntityFailuresException} será lançada.
+ * @return um objeto {@link ShelterEntity} correspondente ao id fornecido ou {@code null} se nenhum {@link ShelterEntity} corresponder ao id fornecido.
+ * @throws ShelterEntityFailuresException Se o id fornecido for nulo, vazio ou não for um UUID válido.
+ * @see #validateId(String)
+ */
+ private ShelterEntity getShelterEntityById(String id) {
+ this.validateId(id);
+ Optional entity = this.findById(id);
+ return entity.orElse(null);
+ }
+
+ /**
+ * Recupera todos os abrigos do banco de dados.
+ *
+ * Esse método recupera todas as entidades de {@link ShelterEntity} presentes no banco de dados, usando o método {@code findAll} da interface {@link CrudRepository}.
+ * Em seguida, realiza o mapeamento dessas entidades para o contrato de abrigo {@link ShelterContract}, usando a função {@code mapEntityList}.
+ * Portanto, este método é responsável por converter as entidades de abrigo representadas no banco de dados em contratos de abrigo que podem ser usados na lógica de negócios da aplicação.
+ *
+ *
+ * @return Uma lista de contratos de abrigo {@link ShelterContract}. Se não houver entidades de abrigo no banco de dados, retorna uma lista vazia.
+ */
+ @Override
+ default List retrieveAll() {
+ List shelterEntityList = (List) this.findAll();
+ return this.mapEntityList(shelterEntityList);
+ }
+
+ /**
+ * Persiste uma instância de {@link ShelterContract} na representação do banco de dados.
+ *
+ * Primeiro, o método mapeia a instância de {@link ShelterContract} fornecida para seu equivalente {@link ShelterEntity}.
+ * A conversão é feita usando uma instância de {@link ShelterEntityMapper}.
+ *
+ * O {@link ShelterEntity} resultante é então passado para o método {@code save} da interface {@link CrudRepository}.
+ * Este método salva a entidade no banco de dados e retorna a entidade persistida.
+ *
+ * Finalmente, a {@link ShelterEntity} persistida é mapeada de volta para um {@link ShelterContract} usando uma instância de {@link ShelterMapper}.
+ * Este {@link ShelterContract} mapeado é então retornado.
+ *
+ * Este método é uma implementação direta da operação padrão de persistência fornecida pela interface {@link CrudRepository}.
+ *
+ * @param entity A instância de {@link ShelterContract} que será persistida. Deve ser um valor não nulo.
+ * @return uma instância de {@link ShelterContract} que representa a entidade persistida.
+ * @throws ShelterEntityFailuresException se a entidade fornecida for nula.
+ * @see CrudRepository
+ */
+ @Override
+ default ShelterContract persist(ShelterContract entity) {
+ ValidationUtils.validateNotNullOrEmpty(entity, SHELTER_ERROR_MESSAGE, ShelterEntityFailuresException.class);
+ ShelterEntity shelterEntity = BuilderMapper.mapTo(new ShelterEntityMapper(), entity);
+ return BuilderMapper.mapTo(this.getShelterMapper(), this.save(shelterEntity));
+ }
+
+ /**
+ * Este método é usado para excluir uma entidade {@link ShelterEntity} pelo ID.
+ *
+ * Primeiramente, o método tenta recuperar a entidade {@link ShelterEntity} correspondente ao ID fornecido por meio
+ * do método {@link #getShelterEntityById(String) getShelterEntityById(String id)}. Se o método não conseguir encontrar qualquer entidade {@link ShelterEntity}
+ * correspondente ao ID fornecido, o método termina e não realiza nenhuma ação.
+ *
+ * Se o método {@link #getShelterEntityById(String) getShelterEntityById(String id)} retornar uma entidade válida, essa entidade é passada para o método
+ * {@link #delete(Object) delete(ShelterEntity targetEntity)}, que se encarrega de excluir a entidade do banco de dados.
+ *
+ * Este método é uma extensão direta do método {@code delete(ID id)} da interface {@link org.springframework.data.repository.CrudRepository}.
+ *
+ * @param id A String que representa o ID único da entidade {@link ShelterEntity} a ser excluída.
+ * Deve ser um valor não nulo e não vazio.
+ * @see ShelterEntity
+ * @see #getShelterEntityById(String)
+ */
+ @Override
+ default void deleteEntityById(String id) {
+ ShelterEntity targetEntity = this.getShelterEntityById(id);
+ if (targetEntity == null) {
+ return;
+ }
+ this.delete(targetEntity);
+ }
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/UserRepository.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/UserRepository.java
new file mode 100644
index 0000000..6d087f5
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/repository/UserRepository.java
@@ -0,0 +1,155 @@
+package diegosneves.github.conectardoacoes.adapters.rest.repository;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.BuilderMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.MapperStrategy;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.UserEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.UserMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
+import diegosneves.github.conectardoacoes.core.domain.user.shared.repository.UserContractRepository;
+
+import java.util.ArrayList;
+import java.util.Collections;
+
+import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
+import diegosneves.github.conectardoacoes.core.utils.UuidUtils;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * A interface do repositório de usuário, {@link UserRepository}, estende as interfaces {@link UserContractRepository} e {@link CrudRepository}.
+ *
+ *
+ * @author diegoneves
+ * @Repository - Esta anotação é uma especialização da anotação @Component, permitindo detecção automática de classes.
+ * Isso também traduzirá qualquer exceção de tempo de execução lançada por classes de repositório,
+ * back-end de dados ou suporte de persistência para a exceção específica do Spring {@link org.springframework.dao.DataAccessException}.
+ * @see UserContractRepository
+ * @see CrudRepository
+ * @since 1.0.0
+ */
+@Repository
+public interface UserRepository extends UserContractRepository, CrudRepository {
+
+ String USER_ID_ERROR_MESSAGE = "Operação não realizada. Um ID de usuário válido deve ser fornecido.";
+ String REQUIRED_USER_ERROR_MESSAGE = "Um usuário válido é requerido para efetuar a persistência.";
+
+ /**
+ * Este método busca um usuário pelo email fornecido e retorna um {@link Optional} de {@link UserEntity}.
+ * Se nenhum usuário for encontrado com o email fornecido,
+ * este método retornará um {@link Optional} vazio.
+ *
+ * @param email O email do usuário a ser buscado.
+ * @return um Optional de UserEntity.
+ */
+ Optional findByEmail(String email);
+
+
+ @Override
+ default UserContract findEntityById(String id) {
+ UserEntity userEntity = this.retrieveUserEntityById(id);
+ if (userEntity == null) return null;
+ return this.getUserMapper().mapFrom(userEntity);
+ }
+
+ /**
+ * Este método retorna uma entidade de usuário com base no ID fornecido.
+ * Antes de tentar recuperar o usuário, o método valida o ID do usuário fornecido.
+ *
+ * Depois de validar o ID do usuário, usando o método {@link #validateUserId(String)}, este método tenta buscar a entidade do
+ * usuário. Se a entidade do usuário não existir, retorna null.
+ *
+ * @param id O ID da entidade do usuário a ser retornada. Não pode ser nulo ou uma String vazia.
+ * @return A {@link UserEntity} que corresponde ao ID fornecido. Se nenhuma {@link UserEntity} corresponder ao fornecido, este
+ * método retorna null.
+ * @throws UserEntityFailuresException Se o ID do usuário fornecido for nulo, vazio ou não for um UUID válido.
+ * @see #validateUserId(String)
+ */
+ private UserEntity retrieveUserEntityById(String id) {
+ this.validateUserId(id);
+ Optional optionalUser = this.findById(id);
+ return optionalUser.orElse(null);
+ }
+
+ /**
+ * Este método é responsável por criar e retornar uma nova instância de {@link UserMapper}.
+ *
+ * A classe {@link UserMapper} é uma implementação da interface {@link MapperStrategy} que fornece
+ * funcionalidade para mapear um objeto {@link UserEntity} (que é compatível com o modelo de dados do banco)
+ * para um objeto {@link User}, que representa o modelo de negócio do sistema. Assim, a classe {@link UserMapper}
+ * ajuda na conversão entre o modelo de dados e o modelo de negócio quando estamos lidando com informações de usuário.
+ *
+ * @return uma nova instância de {@link UserMapper}.
+ */
+ private UserMapper getUserMapper() {
+ return new UserMapper();
+ }
+
+ /**
+ * Método de validação do ID do usuário.
+ * Este método realiza duas verificações principais:
+ *
+ * - Certifica-se de que o ID do usuário não é nulo ou vazio.
+ * - Certifica-se de que o ID do usuário é um UUID válido.
+ *
+ *
+ * Caso alguma dessas verificações falhe, uma {@link UserEntityFailuresException} será lançada.
+ *
+ * @param id O ID do usuário que deve ser validado.
+ * @throws UserEntityFailuresException Se o ID do usuário for nulo, vazio ou não for um UUID válido.
+ */
+ private void validateUserId(String id) throws UserEntityFailuresException {
+ ValidationUtils.validateNotNullOrEmpty(id, USER_ID_ERROR_MESSAGE, UserEntityFailuresException.class);
+ try {
+ UuidUtils.isValidUUID(id);
+ } catch (UuidUtilsException e) {
+ throw new UserEntityFailuresException(USER_ID_ERROR_MESSAGE, e);
+ }
+ }
+
+ @Override
+ default List retrieveAll() {
+ List allUsers = (List) this.findAll();
+ return this.mapEntityList(allUsers);
+ }
+
+ /**
+ * Este método é usado para mapear uma lista de objetos {@link UserEntity} para uma lista de objetos {@link UserContract}.
+ *
+ *
+ * Se a lista de {@link UserEntity} fornecida é nula ou vazia, o método retorna uma lista vazia imutável. Caso contrário,
+ * o método itera sobre esta lista, mapeando cada objeto {@link UserEntity} para sua representação como
+ * um objeto {@link UserContract}, usando {@link UserMapper#mapFrom(UserEntity)} para realizar a transformação.
+ *
+ *
+ * @param entities uma lista de {@link UserEntity} a serem mapeados para objetos {@link UserContract}. Pode ser nula ou vazia.
+ * @return uma lista de objetos {@link UserContract} correspondente aos {@link UserEntity}'s fornecidos.
+ * Se o {@link UserEntity} for nulo ou vazio, uma lista vazia imutável é retornada.
+ */
+ private List mapEntityList(List entities) {
+ if (entities == null || entities.isEmpty()) return Collections.emptyList();
+ return entities.stream().map(this.getUserMapper()::mapFrom).toList();
+ }
+
+
+ @Override
+ default UserContract persist(UserContract entity) {
+ ValidationUtils.validateNotNullOrEmpty(entity, REQUIRED_USER_ERROR_MESSAGE, UserEntityFailuresException.class);
+ UserEntity userEntity = BuilderMapper.mapTo(new UserEntityMapper(), entity);
+ return BuilderMapper.mapTo(this.getUserMapper(), this.save(userEntity));
+ }
+
+ @Override
+ default void deleteEntityById(String id) {
+ UserEntity targetEntity = this.retrieveUserEntityById(id);
+ if (targetEntity == null) return;
+ this.delete(targetEntity);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/request/ShelterCreationRequest.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/request/ShelterCreationRequest.java
new file mode 100644
index 0000000..ae9247c
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/request/ShelterCreationRequest.java
@@ -0,0 +1,41 @@
+package diegosneves.github.conectardoacoes.adapters.rest.request;
+
+import diegosneves.github.conectardoacoes.adapters.rest.dto.AddressDTO;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Classe modelo para o Pedido de Criação do Abrigo {@link ShelterCreationRequest}. Esta classe é usada para a criação de um novo abrigo.
+ * Contém informações essenciais para a criação de um abrigo, incluindo o nome do abrigo,
+ * um {@link AddressDTO} representando o endereço do abrigo, e o {@code e-mail} do usuário responsável pelo abrigo.
+ *
+ * Exemplo de uso:
+ *
+ * {@code
+ * ShelterCreatedRequest shelterRequest = ShelterCreatedRequest.builder()
+ * .shelterName("Little Paws")
+ * .addressDTO(address)
+ * .responsibleUserEmail("admin@littlepaws.com")
+ * .build();
+ * }
+ *
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ * @see AddressDTO
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Builder
+public class ShelterCreationRequest {
+
+ private String shelterName;
+ private AddressDTO address;
+ private String responsibleUserEmail;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/request/UserEntityCreationRequest.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/request/UserEntityCreationRequest.java
new file mode 100644
index 0000000..537641a
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/request/UserEntityCreationRequest.java
@@ -0,0 +1,42 @@
+package diegosneves.github.conectardoacoes.adapters.rest.request;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Esta classe representa um objeto de solicitação para a criação de uma nova entidade de usuário.
+ * Ela é usada principalmente para coletar detalhes sobre o novo usuário para criar um registro correspondente no banco de dados.
+ *
+ * Os detalhes a serem coletados incluem:
+ *
+ * - userName: o nome de usuário escolhido pelo novo usuário.
+ * - email: o endereço de e-mail do novo usuário.
+ * - userProfile: o tipo de perfil do usuário que classifica o novo usuário em uma de várias categorias possíveis (por exemplo, administrador, usuário regular, etc.).
+ * - userPassword: a senha escolhida pelo novo usuário.
+ *
+ *
+ * Os atributos da classe estão sujeitos a alterações conforme o processamento prossegue.
+ *
+ * Atenção: Esta classe faz uso das anotações Lombok para reduzir a verbosidade do código Java.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ * @see UserProfileType
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Builder
+public class UserEntityCreationRequest {
+
+ private String userName;
+ private String email;
+ private UserProfileType userProfile;
+ private String userPassword;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/response/ShelterCreatedResponse.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/response/ShelterCreatedResponse.java
new file mode 100644
index 0000000..51b8873
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/response/ShelterCreatedResponse.java
@@ -0,0 +1,35 @@
+package diegosneves.github.conectardoacoes.adapters.rest.response;
+
+import diegosneves.github.conectardoacoes.adapters.rest.dto.AddressDTO;
+import diegosneves.github.conectardoacoes.adapters.rest.dto.UserEntityDTO;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Classe modelo {@code DTO} para a resposta de criação de um abrigo.
+ *
+ * Esta classe contém informações sobre a resposta da criação de um abrigo, incluindo o {@code id} do novo abrigo,
+ * o {@code nome} do abrigo, o {@code endereço} do abrigo, e o {@code usuário responsável} pela criação do abrigo.
+ *
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ * @see AddressDTO
+ * @see UserEntityDTO
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Builder
+public class ShelterCreatedResponse {
+
+ private String id;
+ private String shelterName;
+ private AddressDTO address;
+ private UserEntityDTO responsibleUser;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/response/UserEntityCreatedResponse.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/response/UserEntityCreatedResponse.java
new file mode 100644
index 0000000..5353798
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/response/UserEntityCreatedResponse.java
@@ -0,0 +1,41 @@
+package diegosneves.github.conectardoacoes.adapters.rest.response;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+/**
+ * Esta classe representa a resposta após a criação de uma entidade de usuário no sistema.
+ * Ela contém informações relevantes sobre o usuário que foi criado, servindo como um objeto de transferência de dados (DTO).
+ *
+ * Atributos:
+ *
+ * - id: Um identificador único para o usuário criado
+ * - userName: O nome de usuário escolhido pelo usuário
+ * - email: O endereço de e-mail fornecido pelo usuário
+ * - userProfile: O tipo de perfil associado a este usuário (por exemplo, administrador, usuário, etc.)
+ *
+ *
+ * Essa classe é construída usando o padrão de design Builder para facilitar a criação de instâncias e é adotada
+ * a biblioteca Lombok para evitar a verbosidade no código.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ * @see UserProfileType
+ */
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@Builder
+public class UserEntityCreatedResponse {
+
+ private String id;
+ private String userName;
+ private String email;
+ private UserProfileType userProfile;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/ShelterEntityService.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/ShelterEntityService.java
new file mode 100644
index 0000000..48f0184
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/ShelterEntityService.java
@@ -0,0 +1,31 @@
+package diegosneves.github.conectardoacoes.adapters.rest.service;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.request.ShelterCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.ShelterCreatedResponse;
+
+/**
+ * Interface para a criação de um novo abrigo no sistema.
+ *
+ * Esta interface fornece um contrato para a implementação de um serviço responsável por
+ * criar abrigos no sistema.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public interface ShelterEntityService {
+
+ /**
+ * Este método é responsável por criar um novo abrigo no sistema.
+ * Ele recebe um objeto {@link ShelterCreationRequest}, que contém as informações necessárias para criar o abrigo,
+ * como o nome do abrigo, o endereço e o e-mail do usuário responsável por criar o abrigo.
+ *
+ * @param request um objeto {@link ShelterCreationRequest} contendo as informações necessárias para criar um novo abrigo.
+ * @return um objeto {@link ShelterCreatedResponse} contendo as informações do abrigo criado.
+ * @throws ShelterEntityFailuresException se ocorrer algum erro durante a criação do abrigo. Isso pode acontecer
+ * se o usuário responsável não for encontrado, se houver um erro na criação do endereço ou
+ * se houver um erro na criação do abrigo em si.
+ */
+ ShelterCreatedResponse createShelter(ShelterCreationRequest request);
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/UserEntityService.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/UserEntityService.java
new file mode 100644
index 0000000..7f08bbf
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/UserEntityService.java
@@ -0,0 +1,54 @@
+package diegosneves.github.conectardoacoes.adapters.rest.service;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.repository.UserRepository;
+import diegosneves.github.conectardoacoes.adapters.rest.request.UserEntityCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.UserEntityCreatedResponse;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
+
+/**
+ * Definição da interface para o serviço que lida com operações relacionadas à entidade do usuário.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public interface UserEntityService {
+
+ /**
+ * Este método é usado para obter uma entidade de usuário pelo seu email.
+ * Primeiramente, o método verifica se o valor do parâmetro de email não é nulo ou vazio.
+ * Se o valor do email for nulo ou vazio, uma exceção {@link UserEntityFailuresException} é lançada ao usuário
+ * com uma mensagem de erro relevante.
+ *
+ * Se o email for válido, o método tentará encontrar uma entidade de usuário que corresponda ao email
+ * usando a interface {@link UserRepository}.
+ * Se não for encontrada uma entidade de usuário para o email fornecido,
+ * o método lançará uma exceção {@link UserEntityFailuresException} com uma mensagem de erro apropriada.
+ *
+ *
+ * @param email A string que representa o email do usuário que será procurado no repositório.
+ * @return A entidade do usuário correspondente ao email fornecido.
+ * @throws UserEntityFailuresException Se nenhuma entidade de usuário puder ser encontrada para o email fornecido
+ * ou o valor do email for nulo ou vazio.
+ */
+ UserContract searchUserByEmail(String email) throws UserEntityFailuresException;
+
+
+ /**
+ * Método para criar uma nova entidade do usuário. Primeiramente, verifica se a solicitação enviada está completa
+ * e se os valores de seus atributos estão de acordo com a regra de negócio da aplicação. Caso contrário,
+ * uma exceção {@link UserEntityFailuresException} é disparada com uma mensagem de erro detalhada.
+ *
+ * Se os dados fornecidos estiverem corretos, o método criará um novo registro de usuário no banco de dados
+ * usando a interface {@link UserRepository}. Ao final, um objeto {@link UserEntityCreatedResponse} é retornado
+ * contendo todos os dados do novo usuário criado.
+ *
+ *
+ * @param request O objeto {@link UserEntityCreationRequest} que contém os dados necessários para a criação do novo usuário.
+ * @return Um objeto {@link UserEntityCreatedResponse} contendo os dados do novo usuário criado.
+ * @throws UserEntityFailuresException Se os dados fornecidos na solicitação estão incompletos ou inconsistentes
+ * ou se ocorrer algum problema durante a criação do novo usuário no banco de dados.
+ */
+ UserEntityCreatedResponse createUserEntity(UserEntityCreationRequest request) throws UserEntityFailuresException;
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/ShelterEntityServiceImpl.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/ShelterEntityServiceImpl.java
new file mode 100644
index 0000000..d4dbee7
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/ShelterEntityServiceImpl.java
@@ -0,0 +1,270 @@
+package diegosneves.github.conectardoacoes.adapters.rest.service.impl;
+
+import diegosneves.github.conectardoacoes.adapters.rest.dto.AddressDTO;
+import diegosneves.github.conectardoacoes.adapters.rest.dto.UserEntityDTO;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.AddressEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.BuilderMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.ShelterEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.model.AddressEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.ShelterEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.repository.AddressRepository;
+import diegosneves.github.conectardoacoes.adapters.rest.repository.DonationRepository;
+import diegosneves.github.conectardoacoes.adapters.rest.repository.ShelterRepository;
+import diegosneves.github.conectardoacoes.adapters.rest.request.ShelterCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.ShelterCreatedResponse;
+import diegosneves.github.conectardoacoes.adapters.rest.service.ShelterEntityService;
+import diegosneves.github.conectardoacoes.adapters.rest.service.UserEntityService;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.ShelterContract;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import diegosneves.github.conectardoacoes.core.domain.shelter.factory.AddressFactory;
+import diegosneves.github.conectardoacoes.core.domain.shelter.factory.ShelterFactory;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
+import diegosneves.github.conectardoacoes.core.exception.AddressCreationFailureException;
+import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * Esta classe é responsável pela implementação dos métodos necessários para gerenciar abrigos no sistema.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ * @see ShelterEntityService
+ */
+@Service
+public class ShelterEntityServiceImpl implements ShelterEntityService {
+
+ public static final String SHELTER_CREATION_ERROR_MESSAGE = "Erro na criação do Abrigo. Confirme se todos os campos do Abrigo estão corretos e tente novamente.";
+ public static final String ADDRESS_CREATION_ERROR = "Erro na criação do endereço. Confirme se todos os campos do endereço estão corretos e tente novamente.";
+ public static final String ERROR_MAPPING_ADDRESS = "Erro durante o mapeamento do endereço para persistência";
+ public static final String USER_RESPONSIBLE_EMAIL_NOT_FOUND_ERROR = "Ops! Não conseguimos encontrar o e-mail do usuário responsável. Por gentileza, tente novamente.";
+
+
+ private final ShelterRepository repository;
+ private final DonationRepository donationRepository;
+ private final AddressRepository addressRepository;
+ private final UserEntityService userEntityService;
+
+ @Autowired
+ public ShelterEntityServiceImpl(ShelterRepository repository, DonationRepository donationRepository, AddressRepository addressRepository, UserEntityService userEntityService) {
+ this.repository = repository;
+ this.donationRepository = donationRepository;
+ this.addressRepository = addressRepository;
+ this.userEntityService = userEntityService;
+ }
+
+ /**
+ * Este método é responsável por criar um novo abrigo no sistema.
+ * Ele recebe um objeto {@link ShelterCreationRequest}, que contém as informações necessárias para criar o abrigo,
+ * como o nome do abrigo, o endereço e o e-mail do usuário responsável por criar o abrigo.
+ *
+ * Internamente, este método realiza as seguintes operações:
+ *
+ * - Cria uma nova instância de {@link ShelterContract} através do método
createAndReturnShelterInstance
,
+ * utilizando as informações do objeto {@link ShelterCreationRequest} fornecido.
+ * - Mapeia o objeto {@link ShelterContract} criado para um objeto {@link ShelterEntity} e o salva no repositório
+ * do sistema utilizando o método {@code mapShelterAndSaveToRepository}.
+ * - Constrói uma resposta para a criação do abrigo utilizando o objeto {@link ShelterEntity} salvo e o retorna.
+ *
+ *
+ * @param request um objeto {@link ShelterCreationRequest} contendo as informações necessárias para criar um novo abrigo.
+ * @return um objeto {@link ShelterCreatedResponse} contendo as informações do abrigo criado.
+ * @throws ShelterEntityFailuresException se ocorrer algum erro durante a criação do abrigo. Isso pode acontecer
+ * se o usuário responsável não for encontrado, se houver um erro na criação do endereço ou
+ * se houver um erro na criação do abrigo em si.
+ */
+ @Override
+ public ShelterCreatedResponse createShelter(ShelterCreationRequest request) {
+ ShelterContract shelterContract = this.createAndReturnShelterInstance(request);
+ ShelterEntity shelterEntity = this.mapShelterAndSaveToRepository(shelterContract);
+ return constructShelterCreatedResponse(shelterEntity);
+ }
+
+ /**
+ * Este método privado é responsável por construir uma resposta para a criação de um abrigo.
+ * Essa resposta é modelada pela classe {@link ShelterCreatedResponse}.
+ *
+ *
+ * O método aceita como parâmetro um objeto {@link ShelterEntity}, que representa um abrigo que foi armazenado no banco de dados.
+ * Este objeto é usado para extrair informações pertinentes que serão incluídas na resposta.
+ *
+ *
+ *
+ * O método segue essas principais etapas:
+ *
+ *
+ * - Inicia a construção de um objeto {@link ShelterCreatedResponse} através do método builder().
+ * - Configura o ID da resposta para corresponder ao ID da {@link ShelterEntity} fornecida.
+ * - Configura o nome do abrigo na resposta para corresponder ao nome do abrigo na {@link ShelterEntity} fornecida.
+ * - Configura o endereço na resposta para corresponder ao endereço da {@link ShelterEntity} fornecida, convertendo a
+ * {@link AddressEntity} para {@link AddressDTO} com o auxílio do método {@code mapTo()} da classe {@link BuilderMapper}.
+ * - Configura o usuário responsável na resposta para corresponder ao usuário responsável na {@link ShelterEntity} fornecida,
+ * convertendo a {@link UserEntity} para {@link UserEntityDTO} com o auxílio do método {@code mapTo()} da classe {@link BuilderMapper}.
+ * - Finaliza a construção do objeto {@link ShelterCreatedResponse} e o retorna.
+ *
+ *
+ * @param shelterEntity um objeto {@link ShelterEntity} que representa um abrigo armazenado no banco de dados.
+ * @return retorna um objeto {@link ShelterCreatedResponse} que contém as informações do abrigo recém-criado.
+ */
+ private static ShelterCreatedResponse constructShelterCreatedResponse(ShelterEntity shelterEntity) {
+ return ShelterCreatedResponse.builder()
+ .id(shelterEntity.getId())
+ .shelterName(shelterEntity.getShelterName())
+ .address(BuilderMapper.mapTo(AddressDTO.class, shelterEntity.getAddress()))
+ .responsibleUser(BuilderMapper.mapTo(UserEntityDTO.class, shelterEntity.getResponsibleUser()))
+ .build();
+ }
+
+ /**
+ * Cria uma nova instância de {@link Shelter} e a retorna.
+ *
+ * Este método é responsável por criar uma nova instância de {@link Shelter} com base nas informações fornecidas no
+ * objeto {@link ShelterCreationRequest}. A nova instância de abrigo é criada usando o método {@code create} do
+ * {@link ShelterFactory}.
+ *
+ *
+ * Antes de criar o abrigo, o método realiza as seguintes ações:
+ *
+ * - Encontra o {@link UserContract} responsável pelo abrigo através do e-mail fornecido no
+ * {@link ShelterCreationRequest}, usando o método {@code findUserByResponsibleEmail}.
+ * - Cria e salva um {@link Address} com base nas informações de endereço fornecidas no
+ * {@link ShelterCreationRequest}, usando o método {@code createAndSaveAddressFromDto}.
+ *
+ *
+ *
+ * @param request um objeto {@link ShelterCreationRequest} contendo as informações para a criação do abrigo.
+ * @return newShelter a nova instância de {@link Shelter} criada.
+ * @throws ShelterEntityFailuresException se ocorrer algum erro durante a criação da entidade Shelter. Isto pode ser devido a
+ * um erro ao encontrar o usuário responsável, um erro ao salvar o endereço, ou um
+ * erro na própria criação do Shelter.
+ */
+ private Shelter createAndReturnShelterInstance(ShelterCreationRequest request) throws ShelterEntityFailuresException {
+ UserContract userContract = this.findUserByResponsibleEmail(request.getResponsibleUserEmail());
+ Address address = this.createAndSaveAddressFromDto(request.getAddress());
+ Shelter newShelter;
+ try {
+ newShelter = ShelterFactory.create(request.getShelterName(), address, userContract);
+ } catch (ShelterCreationFailureException e) {
+ throw new ShelterEntityFailuresException(SHELTER_CREATION_ERROR_MESSAGE, e);
+ }
+ return newShelter;
+ }
+
+ /**
+ * Este é um método privado na classe {@link ShelterEntityServiceImpl} que é responsável por procurar um usuário por meio do seu e-mail.
+ *
+ * O método é designado para encontrar um {@link UserContract} com base no e-mail do usuário responsável fornecido como um
+ * parâmetro string.
+ *
+ *
+ * O método se encarrega de chamar a função {@code searchUserByEmail} da entidade de serviço do usuário. Se for encontrada alguma
+ * exceção {@link UserEntityFailuresException} durante a execução da função {@code searchUserByEmail}, este método irá pegá-la e lançar
+ * uma nova exceção do tipo {@link ShelterEntityFailuresException} com uma mensagem {@code USER_NOT_FOUND}, acompanhada da exceção original.
+ *
+ *
+ * @param responsibleUserEmail é uma string que representa o e-mail do usuário responsável pelo abrigo que estamos
+ * procurando. Este parâmetro é utilizado para executar a pesquisa do usuário na entidade de serviço do usuário.
+ * @return retorna um objeto {@link UserContract} que representa o usuário encontrato. Este objeto contém todos os detalhes
+ * do usuário que foi buscado por meio de seu e-mail.
+ * @throws ShelterEntityFailuresException é uma exceção que é lançada se houver algum problema ao procurar o usuário
+ * na entidade de serviço do usuário. Esta exceção é acompanhada com a mensagem {@code USER_NOT_FOUND} que descreve o motivo do
+ * lançamento da exceção.
+ */
+ private UserContract findUserByResponsibleEmail(String responsibleUserEmail) throws ShelterEntityFailuresException {
+ UserContract foundUser;
+ try {
+ foundUser = this.userEntityService.searchUserByEmail(responsibleUserEmail);
+ } catch (UserEntityFailuresException e) {
+ throw new ShelterEntityFailuresException(USER_RESPONSIBLE_EMAIL_NOT_FOUND_ERROR, e);
+ }
+ return foundUser;
+ }
+
+ /**
+ * Este método privado é responsável por criar e salvar um endereço a partir de um
+ * objeto {@link AddressDTO} fornecido, e retorna uma instância de {@link Address}.
+ *
+ *
+ * O método inicia validando se o objeto {@link AddressDTO} fornecido não é nulo ou vazio,
+ * lançando uma exceção {@link ShelterEntityFailuresException} com a mensagem
+ * {@code ADDRESS_CREATION_ERROR} se a validação falhar.
+ *
+ *
+ *
+ * Posteriormente, cria uma nova instância de {@link Address} usando a {@link AddressFactory}.
+ * Se ocorrer um {@link AddressCreationFailureException} durante a criação do endereço,
+ * o método captura a exceção e lança uma nova exceção {@link ShelterEntityFailuresException} com
+ * a mensagem {@code ADDRESS_CREATION_ERROR} e a exceção original anexada.
+ *
+ *
+ *
+ * Finalmente, o método usa a instância {@link Address} criada para salvar o endereço no
+ * repositório. O endereço criado é finalmente retornado.
+ *
+ *
+ * @param address é um objeto {@link AddressDTO} que contém as informações do endereço
+ * a serem salvas.
+ * @return Retorna uma instância de {@link Address} que representa o endereço
+ * que foi salvo no repositório.
+ * @throws ShelterEntityFailuresException se a validação do objeto {@link AddressDTO} falhar
+ * ou se ocorrer um erro ao criar um novo {@link Address}.
+ */
+ private Address createAndSaveAddressFromDto(AddressDTO address) throws ShelterEntityFailuresException {
+ ValidationUtils.validateNotNullOrEmpty(address, ADDRESS_CREATION_ERROR, ShelterEntityFailuresException.class);
+ Address newAddress;
+ try {
+ newAddress = AddressFactory.create(address.getStreet(), address.getNumber(), address.getNeighborhood(), address.getCity(), address.getState(), address.getZip());
+ } catch (AddressCreationFailureException e) {
+ throw new ShelterEntityFailuresException(ADDRESS_CREATION_ERROR, e);
+ }
+ this.mapAddressAndSaveToRepository(newAddress);
+ return newAddress;
+ }
+
+ /**
+ * Este método é responsável por mapear um objeto de endereço para a entidade relevante e salvá-lo no repositório.
+ * Usa o {@link BuilderMapper} para mapear o endereço, depois salva no repositório.
+ *
+ * @param address - Um objeto de endereço que precisa ser mapeado e salvo.
+ * @throws ShelterEntityFailuresException - Se ocorrer uma exceção durante o mapeamento, será lançada uma {@link ShelterEntityFailuresException}.
+ * A exceção original será anexada como causa.
+ */
+ private void mapAddressAndSaveToRepository(Address address) throws ShelterEntityFailuresException {
+ AddressEntity addressEntity;
+ try {
+ addressEntity = BuilderMapper.mapTo(new AddressEntityMapper(), address);
+ } catch (RuntimeException e) {
+ throw new ShelterEntityFailuresException(ERROR_MAPPING_ADDRESS, e);
+ }
+ this.addressRepository.save(addressEntity);
+ }
+
+ /**
+ * Este método é responsável por mapear um contrato de abrigo para uma entidade de abrigo e salvá-la no repositório.
+ *
+ * O método primeiro tenta persistir o contrato de abrigo no repositório.
+ * Se a operação for bem-sucedida, ele mapeia o contrato de abrigo salvo para uma nova entidade de abrigo usando um mapeador.
+ * Se ocorrer uma {@link RuntimeException} durante qualquer uma dessas operações, ela é capturada e tratada lançando uma {@link ShelterEntityFailuresException}.
+ *
+ * @param shelterContract é o contrato de abrigo que será mapeado para uma entidade de abrigo e salvo.
+ * @return Retorna a nova entidade de abrigo que foi mapeada e salva com sucesso.
+ * @throws ShelterEntityFailuresException essa exceção é lançada quando ocorre um erro durante a criação da entidade de abrigo.
+ * A causa original da falha é encapsulada dentro desta exceção para permitir uma depuração mais eficiente.
+ */
+ private ShelterEntity mapShelterAndSaveToRepository(ShelterContract shelterContract) {
+ ShelterEntity newShelterEntity;
+ try {
+ ShelterContract savedContract = this.repository.persist(shelterContract);
+ newShelterEntity = BuilderMapper.mapTo(new ShelterEntityMapper(), savedContract);
+ } catch (RuntimeException e) {
+ throw new ShelterEntityFailuresException(SHELTER_CREATION_ERROR_MESSAGE, e);
+ }
+ return newShelterEntity;
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/UserEntityServiceImpl.java b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/UserEntityServiceImpl.java
new file mode 100644
index 0000000..b7aae0a
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/UserEntityServiceImpl.java
@@ -0,0 +1,152 @@
+package diegosneves.github.conectardoacoes.adapters.rest.service.impl;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.BuilderMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.UserEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.UserMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.repository.UserRepository;
+import diegosneves.github.conectardoacoes.adapters.rest.request.UserEntityCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.UserEntityCreatedResponse;
+import diegosneves.github.conectardoacoes.adapters.rest.service.UserEntityService;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import diegosneves.github.conectardoacoes.core.domain.user.factory.UserFactory;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+/**
+ * A classe {@link UserEntityServiceImpl} implementa a interface {@link UserEntityService} e
+ * lida com a lógica de negócios das operações de usuário.
+ * A classe é marcada como um componente do Spring com a anotação {@link Service},
+ * o que permite ao Spring detectar e gerenciar as instâncias dessa classe.
+ *
+ * Além disso, a classe lida com cenários de erros e exceções, lançando uma exceção personalizada
+ * chamada {@link UserEntityFailuresException} quando um problema ocorre.
+ *
+ * @author diegoneves
+ * @see UserEntityService
+ * @see UserEntityFailuresException
+ * @see Service
+ * @since 1.0.0
+ */
+@Service
+public class UserEntityServiceImpl implements UserEntityService {
+
+ public static final String INVALID_EMAIL_ERROR_MESSAGE = "Não foi informado nenhum email. Por favor, forneça um email válido.";
+ public static final String EMAIL_NOT_FOUND_ERROR_MESSAGE = "Não foi possivel encontrar um usuário com o email [ %s ].";
+ public static final String EMAIL_ALREADY_IN_USE = "Desculpe, o endereço de email fornecido já está associado a uma conta existente. Por favor, tente com um email diferente.";
+ public static final String USER_CREATION_FAILURE_MESSAGE = "Ops! A criação do novo usuário não foi bem-sucedida. Por favor, certifique-se de que seus dados estão corretos e tente novamente.";
+ public static final String USER_PROFILE_VALIDATION_FAILURE = "A validação do Perfil do usuário fornecido falhou.";
+ public static final String MISSING_USER_ENTITY_REQUEST_ERROR_MESSAGE = "Por favor, forneça uma requisição de criação de usuário preenchida corretamente.";
+
+
+ private final UserRepository userRepository;
+
+ @Autowired
+ public UserEntityServiceImpl(UserRepository userRepository) {
+ this.userRepository = userRepository;
+ }
+
+ @Override
+ public UserContract searchUserByEmail(String email) throws UserEntityFailuresException {
+ ValidationUtils.validateNotNullOrEmpty(email, INVALID_EMAIL_ERROR_MESSAGE, UserEntityFailuresException.class);
+ UserEntity foundUser = this.userRepository.findByEmail(email).orElseThrow(() -> new UserEntityFailuresException(String.format(EMAIL_NOT_FOUND_ERROR_MESSAGE, email)));
+ return BuilderMapper.mapTo(new UserMapper(), foundUser);
+ }
+
+ @Override
+ public UserEntityCreatedResponse createUserEntity(UserEntityCreationRequest request) throws UserEntityFailuresException {
+ ValidationUtils.validateNotNullOrEmpty(request, MISSING_USER_ENTITY_REQUEST_ERROR_MESSAGE, UserEntityFailuresException.class);
+ this.checkIfEmailAlreadyInUse(request.getEmail());
+ UserEntity newUser = createUserEntityFromCreationRequest(request);
+ return BuilderMapper.mapTo(UserEntityCreatedResponse.class, this.userRepository.save(newUser));
+ }
+
+ /**
+ * Método auxiliar usado para converter uma instância de {@link UserEntityCreationRequest} para uma instância de {@link UserEntity}.
+ *
+ * Este método recebe uma solicitação de criação de entidade de usuário, gera um contrato de usuário correspondente através de
+ * {@link UserEntityServiceImpl#createUserFromRequest(UserEntityCreationRequest)} e usa um {@link UserEntityMapper} para mapear
+ * o contrato de usuário para uma entidade de usuário.
+ *
+ * @param request Uma instância de {@link UserEntityCreationRequest} representando a solicitação de criação de uma nova entidade de usuário.
+ * @return userEntity Uma instância de {@link UserEntity} representando a entidade de usuário recém-criada.
+ * @throws UserEntityFailuresException Se ocorrer um erro durante a criação do usuário ou mapeamento de contrato de usuário para entidade de usuário.
+ * A exceção encapsula e fornece mais detalhes sobre a natureza específica do erro.
+ * @see UserEntityCreationRequest
+ * @see UserEntity
+ * @see UserEntityMapper
+ */
+ private static UserEntity createUserEntityFromCreationRequest(UserEntityCreationRequest request) {
+ UserContract userContract = createUserFromRequest(request);
+ return BuilderMapper.mapTo(new UserEntityMapper(), userContract);
+ }
+
+ /**
+ * Método auxiliar para criar um {@link User} a partir de uma solicitação de criação de entidade de usuário {@link UserEntityCreationRequest}.
+ *
+ * Este método é utilizado principalmente para transformar a solicitação de criação de entidade de usuário em uma instância concreta de {@link User}.
+ * Ele lida com a validação da solicitação e a criação do usuário, lançando uma exceção {@link UserEntityFailuresException} caso algum problema ocorra.
+ * A exceção lança detalhes específicos sobre a natureza do erro.
+ * O perfil do usuário é validado e convertido para um tipo de enumeração {@link UserProfile} apropriado.
+ *
+ * Exceções
+ *
+ * O método lança a exceção {@link UserEntityFailuresException} nas seguintes situações:
+ *
+ * - Quando o campo userProfile da solicitação de criação de entidade de usuário está nulo.
+ * - Quando ocorrer uma exceção {@link RuntimeException} durante a criação do usuário no método {@link UserFactory#create}.
+ *
+ * Nesses casos, uma {@link UserEntityFailuresException} será lançada com uma mensagem de erro adequada.
+ *
+ *
+ * @param request uma solicitação de criação de entidade de usuário formada por userName, email, userProfile e userPassword.
+ * @return User uma instância de {@link User} representando o novo usuário criado.
+ * @throws UserEntityFailuresException lançada quando a validação do userProfile falha ou é impossível criar o usuário devido a uma {@link RuntimeException}.
+ * @see User
+ * @see UserContract
+ * @see UserEntityCreationRequest
+ */
+ private static UserContract createUserFromRequest(UserEntityCreationRequest request) {
+ ValidationUtils.validateNotNullOrEmpty(request.getUserProfile(), USER_PROFILE_VALIDATION_FAILURE, UserEntityFailuresException.class);
+ UserProfile userProfile = Enum.valueOf(UserProfile.class, request.getUserProfile().name());
+ UserContract createdUser;
+ try {
+ createdUser = UserFactory.create(request.getUserName(), request.getEmail(), userProfile, request.getUserPassword());
+ } catch (RuntimeException e) {
+ throw new UserEntityFailuresException(USER_CREATION_FAILURE_MESSAGE, e);
+ }
+ return createdUser;
+ }
+
+ /**
+ * Este método recebe como parâmetro um endereço de email no formato String e verifica se este email já está
+ * registrado no repositório de usuários. A verificação de registro é feita a partir do método
+ * {@link UserRepository#findByEmail(String)}, que retorna um {@link Optional} de {@link UserEntity}.
+ *
+ * Primeiro, o método utiliza a função {@link ValidationUtils#validateNotNullOrEmpty(Object, String, Class)}
+ * para assegurar que o email fornecido não é nulo ou vazio.
+ *
+ * Se a verificação retorna um {@link UserEntity}, isso significa que o endereço de email já existe na base de dados do
+ * sistema, neste caso, uma exceção {@link UserEntityFailuresException} é lançada com uma mensagem predefinida
+ * {@link #EMAIL_ALREADY_IN_USE}.
+ *
+ * Já se a instância de {@link UserEntity} for vazia, ou seja, se o email não foi registrado anteriormente no sistema,
+ * a operação prossegue normalmente sem lançar nenhuma exceção.
+ *
+ * @param email o endereço de email a ser verificado.
+ * @throws UserEntityFailuresException Caso o email fornecido seja nulo ou vazio, ou, caso o email já esteja em uso por um usuário existente.
+ */
+ private void checkIfEmailAlreadyInUse(String email) {
+ ValidationUtils.validateNotNullOrEmpty(email, INVALID_EMAIL_ERROR_MESSAGE, UserEntityFailuresException.class);
+ Optional existingUser = this.userRepository.findByEmail(email);
+ if (existingUser.isPresent()) {
+ throw new UserEntityFailuresException(EMAIL_ALREADY_IN_USE);
+ }
+ }
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/Shelter.java b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/Shelter.java
index ccbc438..bfd6c25 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/Shelter.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/Shelter.java
@@ -74,9 +74,9 @@ private void validateData() throws ShelterCreationFailureException {
} catch (UuidUtilsException e) {
throw new ShelterCreationFailureException(ID_VALIDATION_FAILURE, e);
}
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.shelterName, SHELTER_NAME_REQUIRED_ERROR, ShelterCreationFailureException.class);
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.address, ADDRESS_REQUIRED_ERROR, ShelterCreationFailureException.class);
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.responsibleUser, RESPONSIBLE_REQUIRED_ERROR, ShelterCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(this.shelterName, SHELTER_NAME_REQUIRED_ERROR, ShelterCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(this.address, ADDRESS_REQUIRED_ERROR, ShelterCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(this.responsibleUser, RESPONSIBLE_REQUIRED_ERROR, ShelterCreationFailureException.class);
}
@@ -107,19 +107,19 @@ public List getDonations() {
@Override
public void changeShelterName(String shelterName) throws ShelterCreationFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(shelterName, SHELTER_NAME_REQUIRED_ERROR, ShelterCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(shelterName, SHELTER_NAME_REQUIRED_ERROR, ShelterCreationFailureException.class);
this.shelterName = shelterName;
}
@Override
public void changeAddress(Address address) throws ShelterCreationFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(address, ADDRESS_REQUIRED_ERROR, ShelterCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(address, ADDRESS_REQUIRED_ERROR, ShelterCreationFailureException.class);
this.address = address;
}
@Override
public void addDonation(Donation donation) throws ShelterCreationFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(donation, DONATION_REQUIRED_ERROR, ShelterCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(donation, DONATION_REQUIRED_ERROR, ShelterCreationFailureException.class);
this.donations.add(donation);
}
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/Address.java b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/Address.java
index 8d72060..a8699a9 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/Address.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/Address.java
@@ -2,12 +2,14 @@
import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
import diegosneves.github.conectardoacoes.core.exception.AddressCreationFailureException;
+import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
+import diegosneves.github.conectardoacoes.core.utils.UuidUtils;
import lombok.Getter;
/**
* Classe {@link Address} representa um endereço físico.
*
- * Um endereço é composto pela rua, número, bairro, cidade, estado e CEP (código postal).
+ * Um endereço é composto pelo id, rua, número, bairro, cidade, estado e CEP (código postal).
* Cada um destes campos é uma string e é validado no momento da criação de um objeto {@link Address}.
* Se um destes campos estiver faltando ou em branco, uma exceção {@link AddressCreationFailureException} será lançada.
*
@@ -25,7 +27,9 @@ public class Address {
public static final String CITY_NAME_ERROR_MESSAGE = "Por favor, certifique-se de que o nome da cidade foi inserido corretamente.";
public static final String STATE_NAME_ERROR_MESSAGE = "Por favor, certifique-se de que o nome do Estado foi inserido corretamente.";
public static final String CEP_ERROR_MESSAGE = "Por favor, certifique-se de que o CEP foi inserido corretamente.";
+ public static final String INVALID_ID_MESSAGE = "Deve ser fornecido um ID válido";
+ private final String id;
private final String street;
private final String number;
private final String neighborhood;
@@ -36,6 +40,7 @@ public class Address {
/**
* Construtor para a classe {@link Address}. Cada um dos parâmetros é usado para definir os detalhes de um endereço.
*
+ * @param id A string que representa o UUID do endereço.
* @param street A string que representa a rua do endereço.
* @param number A string que representa o número da residência no endereço.
* @param neighborhood A string que representa o bairro do endereço.
@@ -48,7 +53,8 @@ public class Address {
* Isso é feito através da verificação de que cada campo não seja nulo nem em branco.
* Se algum campo for inválido, será lançada uma exceção {@link AddressCreationFailureException} específica para aquele campo.
*/
- public Address(String street, String number, String neighborhood, String city, String state, String zip) {
+ public Address(String id, String street, String number, String neighborhood, String city, String state, String zip) {
+ this.id = id;
this.street = street;
this.number = number;
this.neighborhood = neighborhood;
@@ -67,6 +73,11 @@ public Address(String street, String number, String neighborhood, String city, S
* a mensagem de erro específica para aquele campo.
*/
private void validateData() {
+ try {
+ UuidUtils.isValidUUID(this.id);
+ } catch (UuidUtilsException e) {
+ throw new AddressCreationFailureException(INVALID_ID_MESSAGE, e);
+ }
this.validateData(this.street, STREET_NAME_ERROR_MESSAGE);
this.validateData(this.number, RESIDENCE_NUMBER_ERROR_MESSAGE);
this.validateData(this.neighborhood, NEIGHBORHOOD_NAME_ERROR_MESSAGE);
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/Donation.java b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/Donation.java
index 1037214..b005b69 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/Donation.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/Donation.java
@@ -1,6 +1,9 @@
package diegosneves.github.conectardoacoes.core.domain.shelter.entity.value;
import diegosneves.github.conectardoacoes.core.exception.DonationRegisterFailureException;
+import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
+import diegosneves.github.conectardoacoes.core.utils.UuidUtils;
+import diegosneves.github.conectardoacoes.core.utils.ValidationUtils;
import lombok.Getter;
/**
@@ -16,18 +19,28 @@ public class Donation {
public static final String INVALID_DESCRIPTION_ERROR = "A descrição da doação está vazia ou nula";
public static final String INVALID_QUANTITY = "A quantidade deve ser maior que zero";
public static final int DEFAULT_DONATION_AMOUNT = 1;
+ public static final String INVALID_ID_MESSAGE = "Deve fornecer um ID válido";
- private String description;
- private Integer amount;
+ private final String id;
+ private final String description;
+ private final Integer amount;
/**
- * Construtor da entidade Donation.
+ * Construtor para criar uma nova instância de doação.
*
- * @param description Descrição da doação.
- * @param amount Quantidade da doação.
- * @throws DonationRegisterFailureException se a descrição ou a quantidade da doação forem inválidos.
+ *
+ * Esse construtor aceita três argumentos que representam o id, a descrição e a quantidade da doação.
+ * Ele valida os argumentos fornecidos e pode lançar uma {@code DonationRegisterFailureException}
+ * se a descrição ou a quantidade fornecida forem inválidas.
+ *
+ *
+ * @param id O identificador único para a doação.
+ * @param description Descrição detalhada da doação.
+ * @param amount Quantidade de doação.
+ * @throws DonationRegisterFailureException Se a descrição é nula ou vazia, ou se a quantidade é nula.
*/
- public Donation(String description, Integer amount) {
+ public Donation(String id, String description, Integer amount) {
+ this.id = id;
this.description = description;
this.amount = this.defaultAmount(amount);
this.validateData();
@@ -39,9 +52,12 @@ public Donation(String description, Integer amount) {
* @throws DonationRegisterFailureException se a descrição da doação for nula ou vazia.
*/
private void validateData() throws DonationRegisterFailureException {
- if (this.description == null || this.description.trim().isEmpty()) {
- throw new DonationRegisterFailureException(INVALID_DESCRIPTION_ERROR);
+ try {
+ UuidUtils.isValidUUID(this.id);
+ } catch (UuidUtilsException e) {
+ throw new DonationRegisterFailureException(INVALID_ID_MESSAGE, e);
}
+ ValidationUtils.validateNotNullOrEmpty(this.description, INVALID_DESCRIPTION_ERROR, DonationRegisterFailureException.class);
}
/**
@@ -52,9 +68,7 @@ private void validateData() throws DonationRegisterFailureException {
* @throws DonationRegisterFailureException se a quantia é nula.
*/
private Integer defaultAmount(Integer amount) throws DonationRegisterFailureException {
- if (amount == null) {
- throw new DonationRegisterFailureException(INVALID_QUANTITY);
- }
+ ValidationUtils.validateNotNullOrEmpty(amount, INVALID_QUANTITY, DonationRegisterFailureException.class);
return (amount < DEFAULT_DONATION_AMOUNT) ? DEFAULT_DONATION_AMOUNT : amount;
}
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/factory/AddressFactory.java b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/factory/AddressFactory.java
new file mode 100644
index 0000000..8d67834
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/factory/AddressFactory.java
@@ -0,0 +1,49 @@
+package diegosneves.github.conectardoacoes.core.domain.shelter.factory;
+
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import diegosneves.github.conectardoacoes.core.exception.AddressCreationFailureException;
+import diegosneves.github.conectardoacoes.core.utils.UuidUtils;
+
+/**
+ * Fábrica estática para a criação de instâncias da classe {@link Address}.
+ *
+ * Esta fábrica oculta a lógica de criação de um endereço, incluindo a geração de um UUID único para cada endereço criado.
+ * Ao encapsular o processo de criação de endereços dentro desta fábrica, o código externo é simplificado e a responsabilidade do controle de versões é mantida dentro da classe {@link AddressFactory} em vez de ser espalhada por várias partes do programa.
+ *
+ * Nota: Esta classe foi projetada para ser usada apenas para a criação de endereços. Não deve ser sub-classificada ou usada como referência. Para criar um novo endereço, use o método {@link #create} desta classe.
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class AddressFactory {
+
+ /**
+ * Construtor privado.
+ *
+ * Isso é usado para assegurar que nenhuma instância da classe {@link AddressFactory} seja criada. A classe {@link AddressFactory} deve ser usada apenas através de chamadas a seu método {@link #create}.
+ * Como tal, um objeto {@link AddressFactory} nunca deve ser instanciado.
+ */
+ private AddressFactory() {
+ }
+
+ /**
+ * Método estático para criação de uma nova instância de {@link Address}.
+ *
+ * Este método é responsável por criar uma nova instância de {@link Address}, que representa um endereço físico, utilizando
+ * os parâmetros fornecidos e gerando um UUID para o novo Endereço.
+ *
+ * @param street A string que representa a rua do endereço.
+ * @param number A string que representa o número da residência no endereço.
+ * @param neighborhood A string que representa o bairro do endereço.
+ * @param city A string que representa a cidade do endereço.
+ * @param state A string que representa o estado do endereço.
+ * @param zip A string que representa o código postal do endereço.
+ * @return Uma nova instância da classe {@link Address} com os parâmetros fornecidos.
+ * @throws AddressCreationFailureException Se algum dos parâmetros fornecidos estiver nulo ou em branco,
+ * conforme validado pela classe {@link Address}.
+ * @see Address
+ */
+ public static Address create(String street, String number, String neighborhood, String city, String state, String zip) throws AddressCreationFailureException {
+ return new Address(UuidUtils.generateUuid(), street, number, neighborhood, city, state, zip);
+ }
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/factory/DonationFactory.java b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/factory/DonationFactory.java
new file mode 100644
index 0000000..06971fe
--- /dev/null
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/factory/DonationFactory.java
@@ -0,0 +1,44 @@
+package diegosneves.github.conectardoacoes.core.domain.shelter.factory;
+
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.exception.DonationRegisterFailureException;
+import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
+import diegosneves.github.conectardoacoes.core.utils.UuidUtils;
+
+/**
+ * Classe utilitária para fornecer funções de fábrica para a criação de instâncias {@link Donation}.
+ *
+ *
+ * Essa classe é usada para isolar a lógica de criação de uma instância de doação, garantindo que sempre seja adequada
+ * para uso assim que for criada.
+ *
+ *
+ *
+ * Essa classe é uma classe de utilitário e não pode ser instanciada. Ela só fornece um método estático.
+ *
+ *
+ * @author diegoneves
+ * @since 1.0.0
+ */
+public class DonationFactory {
+
+ /**
+ * Construtor privado para evitar a instânciação de uma classe de utilitário.
+ */
+ private DonationFactory() {}
+
+ /**
+ * Cria e retorna uma nova instância de doação.
+ *
+ * @param description Descrição da doação a ser criada.
+ * @param amount A quantidade da doação a ser criada.
+ * @return Uma nova instância de doação.
+ *
+ * @throws DonationRegisterFailureException Se as regras de validação da doação falharem.
+ * @throws UuidUtilsException Se a geração do UUID falhar.
+ */
+ public static Donation created(String description, Integer amount) {
+ return new Donation(UuidUtils.generateUuid(), description, amount);
+ }
+
+}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/shared/repository/ShelterRepository.java b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/shared/repository/ShelterContractRepository.java
similarity index 85%
rename from src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/shared/repository/ShelterRepository.java
rename to src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/shared/repository/ShelterContractRepository.java
index 5f77e14..d436851 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/shared/repository/ShelterRepository.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/domain/shelter/shared/repository/ShelterContractRepository.java
@@ -5,7 +5,7 @@
import diegosneves.github.conectardoacoes.core.repository.RepositoryContract;
/**
- * A interface {@link ShelterRepository} herda da interface {@link RepositoryContract}.
+ * A interface {@link ShelterContractRepository} herda da interface {@link RepositoryContract}.
* Ela define o contrato para um repositório que persiste e recupera as entidades {@link ShelterContract}.
*
* Tem as seguintes operações básicas:
@@ -24,6 +24,6 @@
* @see RepositoryContract
* @see Shelter
*/
-public interface ShelterRepository extends RepositoryContract {
+public interface ShelterContractRepository extends RepositoryContract {
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/domain/user/entity/User.java b/src/main/java/diegosneves/github/conectardoacoes/core/domain/user/entity/User.java
index 79faa7c..d0cfd77 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/domain/user/entity/User.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/domain/user/entity/User.java
@@ -76,15 +76,15 @@ public User(String id, String userName, String email, UserProfile userProfile, S
* faltando, em branco ou é inválido
*/
private void validateData() throws UserCreationFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.userProfile, PROFILE_NOT_PROVIDED, UserCreationFailureException.class);
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.userName, String.format(USERNAME_REQUIRED, this.userProfile), UserCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(this.userProfile, PROFILE_NOT_PROVIDED, UserCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(this.userName, String.format(USERNAME_REQUIRED, this.userProfile), UserCreationFailureException.class);
try {
UuidUtils.isValidUUID(this.id);
} catch (UuidUtilsException e) {
throw new UserCreationFailureException(USER_ID_REQUIRED, e);
}
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.email, EMAIL_NOT_PROVIDED, UserCreationFailureException.class);
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.userPassword, PASSWORD_NOT_PROVIDED, UserCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(this.email, EMAIL_NOT_PROVIDED, UserCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(this.userPassword, PASSWORD_NOT_PROVIDED, UserCreationFailureException.class);
}
@@ -115,13 +115,13 @@ public String getEmail() {
@Override
public void changeUserPassword(String password) throws UserCreationFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(password, PASSWORD_NOT_PROVIDED, UserCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(password, PASSWORD_NOT_PROVIDED, UserCreationFailureException.class);
this.userPassword = password;
}
@Override
public void changeUserName(String updatedUsername) {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(updatedUsername, String.format(USERNAME_REQUIRED, this.userProfile), UserCreationFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(updatedUsername, String.format(USERNAME_REQUIRED, this.userProfile), UserCreationFailureException.class);
this.userName = updatedUsername;
}
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/domain/user/shared/repository/UserRepository.java b/src/main/java/diegosneves/github/conectardoacoes/core/domain/user/shared/repository/UserContractRepository.java
similarity index 58%
rename from src/main/java/diegosneves/github/conectardoacoes/core/domain/user/shared/repository/UserRepository.java
rename to src/main/java/diegosneves/github/conectardoacoes/core/domain/user/shared/repository/UserContractRepository.java
index 5f12dae..5d8cac2 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/domain/user/shared/repository/UserRepository.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/domain/user/shared/repository/UserContractRepository.java
@@ -4,7 +4,7 @@
import diegosneves.github.conectardoacoes.core.repository.RepositoryContract;
/**
- * A interface {@link UserRepository} herda de {@link RepositoryContract} que é parametrizada com {@link UserContract}.
+ * A interface {@link UserContractRepository} herda de {@link RepositoryContract} que é parametrizada com {@link UserContract}.
* Ela fornece funcionalidades específicas ao usuário como adicionar, atualizar, deletar e procurar informações de usuários no banco de dados.
*
* Os métodos herdados de {@link RepositoryContract} devem ser implementados em uma classe de repositório de usuário para fornecer o impacto
@@ -13,10 +13,10 @@
*
Os detalhes de cada operação são como segue:
*
*
- * - {@link RepositoryContract#save(Object) save(UserContract entity)} - Salva ou atualiza as informações de um usuário no banco de dados
- *
- {@link RepositoryContract#findById(String id) findById(String id)} - Retorna um usuário procurando pelo ID
- *
- {@link RepositoryContract#findAll() findAll()} - Retorna todos os usuários do banco de dados
- *
- {@link RepositoryContract#deleteById(String id) deleteById(String id)} - Busca e deleta o usuário pelo ID
+ *
- {@link RepositoryContract#persist(Object) persist(UserContract entity)} - Salva ou atualiza as informações de um usuário no banco de dados
+ *
- {@link RepositoryContract#findEntityById(String id) findEntityById(String id)} - Retorna um usuário procurando pelo ID
+ *
- {@link RepositoryContract#retrieveAll() retrieveAll()} - Retorna todos os usuários do banco de dados
+ *
- {@link RepositoryContract#deleteEntityById(String id) deleteEntityById(String id)} - Busca e deleta o usuário pelo ID
*
*
* Caso as operações de pesquisa não possam encontrar usuário(s) correspondente, eles retornarão um valor nulo ou uma lista vazia.
@@ -26,6 +26,6 @@
* @see RepositoryContract
* @see UserContract
*/
-public interface UserRepository extends RepositoryContract {
+public interface UserContractRepository extends RepositoryContract {
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/exception/AddressCreationFailureException.java b/src/main/java/diegosneves/github/conectardoacoes/core/exception/AddressCreationFailureException.java
index 635b159..658d7cb 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/exception/AddressCreationFailureException.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/exception/AddressCreationFailureException.java
@@ -21,6 +21,18 @@
* }
*
*
+ *
+ *
+ * {@code
+ * try {
+ * // código de criação de um Endereço.
+ * } catch (AlgumaExcecao e) {
+ * throw new AdressCreationFailureException("Detalhe da falha", e);
+ * }
+ * }
+ *
+ *
+ *
* @author diegosneves
* @see RuntimeException
* @since 1.0.0
@@ -39,4 +51,18 @@ public AddressCreationFailureException(String message) {
super(ERROR.buildMessage(message));
}
+ /**
+ * Construtor para AddressCreationFailureException. Este construtor aceita uma mensagem e uma causa {@link Throwable}.
+ * Ele chama o construtor da superclasse ({@link RuntimeException}), passando uma mensagem de erro construída usando o objeto {@code ERROR} e a string de mensagem fornecida,
+ * juntamente com a causa {@link Throwable} da exceção.
+ * Este construtor é particularmente útil quando uma exceção é capturada no bloco {@code try} e precisa ser envolvida em uma {@link AddressCreationFailureException}.
+ * A causa {@link Throwable} ajuda a manter a cadeia de exceções para uma melhor depuração.
+ *
+ * @param message O detalhe específico desta instância de falha ao criar um Endereço.
+ * @param cause A exceção original que causou a falha.
+ */
+ public AddressCreationFailureException(String message, Throwable cause) {
+ super(ERROR.buildMessage(message), cause);
+ }
+
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/exception/DonationRegisterFailureException.java b/src/main/java/diegosneves/github/conectardoacoes/core/exception/DonationRegisterFailureException.java
index c975f44..eab59f1 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/exception/DonationRegisterFailureException.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/exception/DonationRegisterFailureException.java
@@ -38,4 +38,14 @@ public DonationRegisterFailureException(String message) {
super(ERROR.buildMessage(message));
}
+ /**
+ * Construtor da classe exceção que aceita uma mensagem de erro e um Throwable como causa da exceção.
+ *
+ * @param message Mensagem de erro específica para a ocorrência da exceção.
+ * @param cause Causa-raíz da exceção.
+ */
+ public DonationRegisterFailureException(String message, Throwable cause) {
+ super(ERROR.buildMessage(message), cause);
+ }
+
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/repository/RepositoryContract.java b/src/main/java/diegosneves/github/conectardoacoes/core/repository/RepositoryContract.java
index 25b1cc9..b52d56c 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/repository/RepositoryContract.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/repository/RepositoryContract.java
@@ -26,14 +26,14 @@ public interface RepositoryContract {
* @param id o identificador único da entidade que deve ser procurada.
* @return a entidade encontrada ou {@code null} se nenhuma entidade com o identificador especificado pôde ser encontrada.
*/
- T findById(String id);
+ T findEntityById(String id);
/**
* Encontra todas as entidades de um determinado tipo.
*
* @return uma lista contendo todas as entidades ou uma lista vazia se não houver entidades.
*/
- List findAll();
+ List retrieveAll();
/**
* Salva uma entidade.
@@ -42,7 +42,7 @@ public interface RepositoryContract {
* @return a entidade salva.
* @throws IllegalArgumentException se a entidade passada como parâmetro for {@code null}.
*/
- T save(T entity);
+ T persist(T entity);
/**
* Deleta uma entidade pelo seu identificador.
@@ -50,6 +50,6 @@ public interface RepositoryContract {
* @param id o identificador único da entidade que deve ser deletada.
* @throws NoSuchElementException se nenhuma entidade com o identificador especificado pôde ser encontrada.
*/
- void deleteById(String id);
+ void deleteEntityById(String id);
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/service/ShelterService.java b/src/main/java/diegosneves/github/conectardoacoes/core/service/ShelterService.java
index 4a48ade..34717dc 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/service/ShelterService.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/service/ShelterService.java
@@ -5,7 +5,7 @@
import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
import diegosneves.github.conectardoacoes.core.domain.shelter.factory.ShelterFactory;
-import diegosneves.github.conectardoacoes.core.domain.shelter.shared.repository.ShelterRepository;
+import diegosneves.github.conectardoacoes.core.domain.shelter.shared.repository.ShelterContractRepository;
import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;
import diegosneves.github.conectardoacoes.core.exception.ShelterServiceFailureException;
@@ -23,7 +23,7 @@
* @author diegoneves
* @since 1.0.0
* @see ShelterServiceContract
- * @see ShelterRepository
+ * @see ShelterContractRepository
*/
public class ShelterService implements ShelterServiceContract {
@@ -32,15 +32,15 @@ public class ShelterService implements ShelterServiceContract {
public static final String ERROR_MESSAGE_ADDRESS_NULL = "O Endereço fornecido não deve ser nulo";
public static final String DONATION_REQUIRED_ERROR_MESSAGE = "A Doação fornecida deve ser válida.";
- private final ShelterRepository shelterRepository;
+ private final ShelterContractRepository shelterContractRepository;
- public ShelterService(ShelterRepository shelterRepository) {
- this.shelterRepository = shelterRepository;
+ public ShelterService(ShelterContractRepository shelterContractRepository) {
+ this.shelterContractRepository = shelterContractRepository;
}
/**
* Este método cria um novo {@link ShelterContract} utilizando {@link ShelterFactory#create}.
- * O novo objeto {@link Shelter} é salvo usando o método {@link ShelterRepository#save}.
+ * O novo objeto {@link Shelter} é salvo usando o método {@link ShelterContractRepository#persist}.
*
* @param shelterName O nome do abrigo como uma string.
* @param address uma instancia do objeto {@link Address} representando o endereço do abrigo
@@ -48,12 +48,12 @@ public ShelterService(ShelterRepository shelterRepository) {
* @return um novo objeto {@link ShelterContract}
* @throws ShelterCreationFailureException quando uma falha ocorre durante a criação do {@link ShelterContract}
* @see ShelterFactory
- * @see ShelterRepository
+ * @see ShelterContractRepository
*/
@Override
public ShelterContract createShelter(String shelterName, Address address, UserContract responsibleUser) throws ShelterCreationFailureException {
Shelter newShelter = ShelterFactory.create(shelterName, address, responsibleUser);
- return this.shelterRepository.save(newShelter);
+ return this.shelterContractRepository.persist(newShelter);
}
/**
@@ -66,12 +66,12 @@ public ShelterContract createShelter(String shelterName, Address address, UserCo
@Override
public ShelterContract getShelter(String shelterId) throws ShelterServiceFailureException {
validateShelterId(shelterId);
- return this.shelterRepository.findById(shelterId);
+ return this.shelterContractRepository.findEntityById(shelterId);
}
/**
* Valida o ID do abrigo fornecido. Primeiro, verifica se o ID do abrigo é nulo ou vazio usando
- * {@link ValidationUtils#checkNotNullAndNotEmptyOrThrowException}. Em seguida, tenta verificar se o ID do abrigo é um UUID válido
+ * {@link ValidationUtils#validateNotNullOrEmpty}. Em seguida, tenta verificar se o ID do abrigo é um UUID válido
* usando {@link UuidUtils#isValidUUID}.
* Se qualquer uma dessas verificações falhar, ele lançará uma {@link ShelterServiceFailureException} com uma mensagem que indica
* que o ID do abrigo fornecido é inválido.
@@ -80,7 +80,7 @@ public ShelterContract getShelter(String shelterId) throws ShelterServiceFailure
* @throws ShelterServiceFailureException Se o ID do abrigo fornecido for nulo, vazio ou não for um UUID válido.
*/
private static void validateShelterId(String shelterId) throws ShelterServiceFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(shelterId, INVALID_SHELTER_ID_MESSAGE, ShelterServiceFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(shelterId, INVALID_SHELTER_ID_MESSAGE, ShelterServiceFailureException.class);
try {
UuidUtils.isValidUUID(shelterId);
} catch (UuidUtilsException e) {
@@ -92,13 +92,13 @@ private static void validateShelterId(String shelterId) throws ShelterServiceFai
* Este método é usado para alterar o nome do abrigo identificado pelo ID fornecido.
*
* Primeiro, o método valida se o novo nome não é nulo nem vazio usando
- * {@link ValidationUtils#checkNotNullAndNotEmptyOrThrowException}. Se a validação falhar,
+ * {@link ValidationUtils#validateNotNullOrEmpty}. Se a validação falhar,
* uma {@link ShelterServiceFailureException} é lançada com uma mensagem indicando que o novo nome do abrigo é inválido.
*
* O nome do abrigo recuperado é então alterado para o novo nome fornecido usando o método
* {@link ShelterContract#changeShelterName}.
*
- * Finalmente, o abrigo com o nome atualizado é salvo no repositório usando {@link ShelterRepository#save}.
+ * Finalmente, o abrigo com o nome atualizado é salvo no repositório usando {@link ShelterContractRepository#persist}.
*
* @param shelterId O ID do abrigo cujo nome será alterado. Deve ser uma identificação válida de um abrigo existente.
* @param newName O novo nome para o abrigo. Ele não pode ser {@code null} ou uma String vazia.
@@ -107,23 +107,23 @@ private static void validateShelterId(String shelterId) throws ShelterServiceFai
*/
@Override
public void changeShelterName(String shelterId, String newName) throws ShelterServiceFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(newName, INVALID_SHELTER_NAME_ERROR_MESSAGE, ShelterServiceFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(newName, INVALID_SHELTER_NAME_ERROR_MESSAGE, ShelterServiceFailureException.class);
ShelterContract updatedShelter = this.getShelter(shelterId);
updatedShelter.changeShelterName(newName);
- this.shelterRepository.save(updatedShelter);
+ this.shelterContractRepository.persist(updatedShelter);
}
/**
* Este método é usado para alterar o endereço do abrigo identificado pelo ID fornecido.
*
* Primeiro, o método valida se o novo endereço não é nulo usando
- * {@link ValidationUtils#checkNotNullAndNotEmptyOrThrowException}. Se a validação falhar,
+ * {@link ValidationUtils#validateNotNullOrEmpty}. Se a validação falhar,
* uma {@link ShelterServiceFailureException} é lançada com uma mensagem indicando que o novo endereço do abrigo é inválido.
*
* O endereço do abrigo recuperado é então alterado para o novo endereço fornecido usando o método
* {@link ShelterContract#changeAddress}.
*
- * Finalmente, o abrigo com o endereço atualizado é salvo no repositório usando {@link ShelterRepository#save}.
+ * Finalmente, o abrigo com o endereço atualizado é salvo no repositório usando {@link ShelterContractRepository#persist}.
*
* @param shelterId O ID do abrigo cujo endereço será alterado. Deve ser uma identificação válida de um abrigo existente.
* @param address O novo endereço para o abrigo. Ele não pode ser {@code null} ou uma instância inválida de {@link Address}.
@@ -132,23 +132,23 @@ public void changeShelterName(String shelterId, String newName) throws ShelterSe
*/
@Override
public void changeAddress(String shelterId, Address address) throws ShelterServiceFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(address, ERROR_MESSAGE_ADDRESS_NULL, ShelterServiceFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(address, ERROR_MESSAGE_ADDRESS_NULL, ShelterServiceFailureException.class);
ShelterContract updatedShelter = this.getShelter(shelterId);
updatedShelter.changeAddress(address);
- this.shelterRepository.save(updatedShelter);
+ this.shelterContractRepository.persist(updatedShelter);
}
/**
* Este método é responsável por adicionar uma {@link Donation} a um {@link ShelterContract} específico, identificado por seu id.
*
* Primeiro, ele confirma que o objeto {@link Donation} não é nulo usando
- * {@link ValidationUtils#checkNotNullAndNotEmptyOrThrowException}. Se este objeto {@link Donation} for nulo,
+ * {@link ValidationUtils#validateNotNullOrEmpty}. Se este objeto {@link Donation} for nulo,
* ele lança uma {@link ShelterServiceFailureException}.
*
* Em seguida, ele usa o id do abrigo fornecido para obter o {@link ShelterContract} correspondente.
* Este {@link ShelterContract} é então atualizado adicionando a {@link Donation} fornecida.
*
- * Finalmente, o {@link ShelterContract} atualizado é salvo no repositorio usando {@link ShelterRepository#save}.
+ * Finalmente, o {@link ShelterContract} atualizado é salvo no repositorio usando {@link ShelterContractRepository#persist}.
*
* @param shelterId O ID do abrigo ao qual a doação será adicionada. Deve ser uma identificação válida de um abrigo existente.
* @param donation Uma instancia do objeto {@link Donation} representando a doação a ser adicionada.
@@ -157,10 +157,10 @@ public void changeAddress(String shelterId, Address address) throws ShelterServi
*/
@Override
public void addDonation(String shelterId, Donation donation) throws ShelterServiceFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(donation, DONATION_REQUIRED_ERROR_MESSAGE, ShelterServiceFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(donation, DONATION_REQUIRED_ERROR_MESSAGE, ShelterServiceFailureException.class);
ShelterContract updatedShelter = this.getShelter(shelterId);
updatedShelter.addDonation(donation);
- this.shelterRepository.save(updatedShelter);
+ this.shelterContractRepository.persist(updatedShelter);
}
/**
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/service/UserService.java b/src/main/java/diegosneves/github/conectardoacoes/core/service/UserService.java
index 161df95..7f9b788 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/service/UserService.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/service/UserService.java
@@ -4,7 +4,7 @@
import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
import diegosneves.github.conectardoacoes.core.domain.user.factory.UserFactory;
-import diegosneves.github.conectardoacoes.core.domain.user.shared.repository.UserRepository;
+import diegosneves.github.conectardoacoes.core.domain.user.shared.repository.UserContractRepository;
import diegosneves.github.conectardoacoes.core.exception.UserCreationFailureException;
import diegosneves.github.conectardoacoes.core.exception.UserServiceFailureException;
import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
@@ -15,14 +15,14 @@
* A classe {@link UserService} implementa um contratato do serviço do usuário {@link UserServiceContract}.
* Ela fornece os métodos para gerenciar usuários, incluindo criação de um novo usuário, recuperação de um usuário pelo seu ID,
* alteração da senha do usuário e alteração do nome de usuário.
- *
Isso é feito por meio da interação com o repositório de usuários {@link UserRepository}, onde os dados do usuário são armazenados.
+ *
Isso é feito por meio da interação com o repositório de usuários {@link UserContractRepository}, onde os dados do usuário são armazenados.
*
Os métodos implementados nesta classe realizam checagens de validação para garantir que os dados do usuário sejam válidos.
* Se quaisquer dados inválidos forem fornecidos, como um ID de usuário, senha ou nome de usuário nulo ou em branco,
* eles lançarão uma exceção {@link UserServiceFailureException}.
*
* @author diegoneves
* @see UserServiceContract
- * @see UserRepository
+ * @see UserContractRepository
* @see UserServiceFailureException
* @since 1.0.0
*/
@@ -33,10 +33,10 @@ public class UserService implements UserServiceContract {
public static final String USER_NOT_FOUND_MESSAGE = "Usuário não encontrado";
public static final String USERNAME_INVALID_ERROR_MESSAGE = "O novo nome de usuário informado é inválido.";
- private final UserRepository userRepository;
+ private final UserContractRepository userContractRepository;
- public UserService(UserRepository userRepository) {
- this.userRepository = userRepository;
+ public UserService(UserContractRepository userContractRepository) {
+ this.userContractRepository = userContractRepository;
}
/**
@@ -52,7 +52,7 @@ public UserService(UserRepository userRepository) {
@Override
public UserContract createUser(String username, String email, UserProfile userProfile, String password) throws UserCreationFailureException {
User newUser = UserFactory.create(username, email, userProfile, password);
- return this.userRepository.save(newUser);
+ return this.userContractRepository.persist(newUser);
}
/**
@@ -65,7 +65,7 @@ public UserContract createUser(String username, String email, UserProfile userPr
@Override
public UserContract getUser(String userId) {
validateUserId(userId);
- return this.userRepository.findById(userId);
+ return this.userContractRepository.findEntityById(userId);
}
/**
@@ -90,7 +90,7 @@ public UserContract getUser(String userId) {
* informação contextual adicional quando o UUID não é válido.
*/
private static void validateUserId(String userId) throws UserServiceFailureException {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(userId, INVALID_IDENTIFIER_ERROR_MESSAGE, UserServiceFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(userId, INVALID_IDENTIFIER_ERROR_MESSAGE, UserServiceFailureException.class);
try {
UuidUtils.isValidUUID(userId);
} catch (UuidUtilsException e) {
@@ -107,11 +107,11 @@ private static void validateUserId(String userId) throws UserServiceFailureExcep
*/
@Override
public void changePassword(String userId, String newPassword) {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(newPassword, INVALID_NEW_PASSWORD_MESSAGE, UserServiceFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(newPassword, INVALID_NEW_PASSWORD_MESSAGE, UserServiceFailureException.class);
UserContract retrievedUser = this.getUser(userId);
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(retrievedUser, USER_NOT_FOUND_MESSAGE, UserServiceFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(retrievedUser, USER_NOT_FOUND_MESSAGE, UserServiceFailureException.class);
retrievedUser.changeUserPassword(newPassword);
- this.userRepository.save(retrievedUser);
+ this.userContractRepository.persist(retrievedUser);
}
/**
@@ -123,10 +123,10 @@ public void changePassword(String userId, String newPassword) {
*/
@Override
public void changeUserName(String userId, String newUsername) {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(newUsername, USERNAME_INVALID_ERROR_MESSAGE, UserServiceFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(newUsername, USERNAME_INVALID_ERROR_MESSAGE, UserServiceFailureException.class);
UserContract retrievedUser = this.getUser(userId);
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(retrievedUser, USER_NOT_FOUND_MESSAGE, UserServiceFailureException.class);
+ ValidationUtils.validateNotNullOrEmpty(retrievedUser, USER_NOT_FOUND_MESSAGE, UserServiceFailureException.class);
retrievedUser.changeUserName(newUsername);
- this.userRepository.save(retrievedUser);
+ this.userContractRepository.persist(retrievedUser);
}
}
diff --git a/src/main/java/diegosneves/github/conectardoacoes/core/utils/ValidationUtils.java b/src/main/java/diegosneves/github/conectardoacoes/core/utils/ValidationUtils.java
index ae90b3d..f4824f0 100644
--- a/src/main/java/diegosneves/github/conectardoacoes/core/utils/ValidationUtils.java
+++ b/src/main/java/diegosneves/github/conectardoacoes/core/utils/ValidationUtils.java
@@ -17,21 +17,18 @@ private ValidationUtils() {
}
/**
- * Valida se o objeto especificado é nulo ou vazio, caso seja uma instância de String.
+ * Valida a entrada com base nas condições para nulo e vazio (no caso de String).
* Lança uma exceção com a mensagem de erro fornecida, se uma destas condições for verdadeira.
* Este método pode ser utilizado para a validação de entradas onde dados são obrigatórios.
*
* @param o tipo de objeto a ser verificado
- * @param object o objeto a ser validado
+ * @param input o objeto a ser validado
* @param errorMessage a mensagem de erro a ser anexada à exceção em caso de falhas na validação
* @param customException a classe da exceção RuntimeException a ser lançada
* @throws RuntimeException se o objeto fornecido for nulo ou se fora uma instância de String e estiver vazia
*/
- public static void checkNotNullAndNotEmptyOrThrowException(T object, String errorMessage, Class extends RuntimeException> customException) throws RuntimeException {
- if (object == null) {
- throwException(errorMessage, customException);
- }
- if (object instanceof String && ((String) object).trim().isEmpty()) {
+ public static void validateNotNullOrEmpty(T input, String errorMessage, Class extends RuntimeException> customException) {
+ if (input == null || (input instanceof String && ((String) input).trim().isEmpty())) {
throwException(errorMessage, customException);
}
}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/controller/imp/ShelterControllerImplTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/controller/imp/ShelterControllerImplTest.java
new file mode 100644
index 0000000..e6605b8
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/controller/imp/ShelterControllerImplTest.java
@@ -0,0 +1,111 @@
+package diegosneves.github.conectardoacoes.adapters.rest.controller.imp;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.dto.AddressDTO;
+import diegosneves.github.conectardoacoes.adapters.rest.dto.UserEntityDTO;
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.request.ShelterCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.ShelterCreatedResponse;
+import diegosneves.github.conectardoacoes.adapters.rest.service.ShelterEntityService;
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.test.web.servlet.ResultActions;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+
+import java.util.Objects;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+@ExtendWith(SpringExtension.class)
+class ShelterControllerImplTest {
+
+ public static final String SHELTER_ID = "56eec2ee-d9ca-40be-aec2-eed9ca90be0b";
+ public static final String SHELTER_NAME = "Nome";
+
+ public static final String STREET = "Rua";
+ public static final String NUMBER = "258";
+ public static final String NEIGHBORHOOD = "Bairro";
+ public static final String CITY = "Cidade";
+ public static final String STATE = "Estado";
+ public static final String ZIP = "98456123";
+
+ public static final String USER_ID = "3925e5e4-7e14-4a15-a5e5-e47e14ca1539";
+ public static final String USER_NAME = "Usuario";
+ public static final String USER_EMAIL = "email@email.com";
+
+
+ @InjectMocks
+ private ShelterControllerImpl shelterController;
+
+ @Mock
+ private ShelterEntityService shelterEntityService;
+
+ private MockMvc mockMvc;
+
+ @BeforeEach
+ void setUp() {
+ this.mockMvc = MockMvcBuilders.standaloneSetup(this.shelterController).build();
+ }
+
+ @Test
+ @SneakyThrows
+ void testCreateShelter() {
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ AddressDTO addressDTO = AddressDTO.builder()
+ .street(STREET)
+ .number(NUMBER)
+ .neighborhood(NEIGHBORHOOD)
+ .city(CITY)
+ .state(STATE)
+ .zip(ZIP)
+ .build();
+
+ UserEntityDTO userDTO = UserEntityDTO.builder()
+ .id(USER_ID)
+ .userName(USER_NAME)
+ .email(USER_EMAIL)
+ .userProfile(UserProfileType.DONOR)
+ .build();
+
+ ShelterCreationRequest request = ShelterCreationRequest.builder()
+ .shelterName(SHELTER_NAME)
+ .address(addressDTO)
+ .responsibleUserEmail(USER_EMAIL)
+ .build();
+
+ ShelterCreatedResponse expectedResponse = ShelterCreatedResponse.builder()
+ .id(SHELTER_ID)
+ .shelterName(SHELTER_NAME)
+ .address(addressDTO)
+ .responsibleUser(userDTO)
+ .build();
+
+ when(this.shelterEntityService.createShelter(any(ShelterCreationRequest.class))).thenReturn(expectedResponse);
+
+ String requestJson = objectMapper.writeValueAsString(request);
+ String expectedResponseJson = objectMapper.writeValueAsString(expectedResponse);
+
+ this.mockMvc.perform(post("/shelter/create")
+ .contentType(MediaType.APPLICATION_JSON)
+ .content(requestJson))
+ .andExpect(status().isCreated())
+ .andExpect(content().json(expectedResponseJson));
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressEntityMapperTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressEntityMapperTest.java
new file mode 100644
index 0000000..fb97f0b
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressEntityMapperTest.java
@@ -0,0 +1,60 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.AddressEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.AddressEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@ExtendWith(MockitoExtension.class)
+class AddressEntityMapperTest {
+
+ public static final String ADDRESS_ID = "4cdc1890-6c94-4d8d-9c18-906c944d8da9";
+ public static final String STREET = "Rua";
+ public static final String NUMBER = "123";
+ public static final String NEIGHBORHOOD = "Bairro";
+ public static final String CITY = "Cidade";
+ public static final String STATE = "Estado";
+ public static final String ZIP = "91234567";
+
+
+ private AddressEntityMapper addressEntityMapper;
+
+ private Address address;
+
+ @BeforeEach
+ void setUp() {
+ this.addressEntityMapper = new AddressEntityMapper();
+ this.address = new Address(ADDRESS_ID, STREET, NUMBER, NEIGHBORHOOD, CITY, STATE, ZIP);
+ }
+
+ @Test
+ void shouldMapAddressEntityToAddress() {
+ AddressEntity addressEntity = this.addressEntityMapper.mapFrom(this.address);
+
+ assertNotNull(addressEntity);
+ assertEquals(ADDRESS_ID, addressEntity.getId());
+ assertEquals(STREET, addressEntity.getStreet());
+ assertEquals(NUMBER, addressEntity.getNumber());
+ assertEquals(NEIGHBORHOOD, addressEntity.getNeighborhood());
+ assertEquals(CITY, addressEntity.getCity());
+ assertEquals(STATE, addressEntity.getState());
+ assertEquals(ZIP, addressEntity.getZip());
+ }
+
+ @Test
+ void shouldThrowExceptionOnMapFromNullAddress() {
+ this.address = null;
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressEntityMapper.mapFrom(this.address));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressEntityMapper.ADDRESS_CLASS.getSimpleName())), exception.getMessage());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressMapperTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressMapperTest.java
new file mode 100644
index 0000000..a72c3c3
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/AddressMapperTest.java
@@ -0,0 +1,186 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.AddressEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.AddressEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@ExtendWith(MockitoExtension.class)
+class AddressMapperTest {
+
+ public static final String ADDRESS_ID = "5e4c5ca9-46d2-42c3-8c5c-a946d242c3dd";
+ public static final String ADDRESS_STREET = "Rua";
+ public static final String ADDRESS_NUMBER = "123";
+ public static final String ADDRESS_NEIGHBORHOOD = "Bairro";
+ public static final String ADDRESS_CITY = "Cidade";
+ public static final String ADDRESS_STATE = "Estado";
+ public static final String ZIP_CODE = "91234567";
+
+ private AddressMapper addressMapper;
+
+ private AddressEntity addressEntity;
+
+ @BeforeEach
+ void setUp() {
+ this.addressMapper = new AddressMapper();
+ this.addressEntity = AddressEntity.builder()
+ .id(ADDRESS_ID)
+ .street(ADDRESS_STREET)
+ .number(ADDRESS_NUMBER)
+ .neighborhood(ADDRESS_NEIGHBORHOOD)
+ .city(ADDRESS_CITY)
+ .state(ADDRESS_STATE)
+ .zip(ZIP_CODE)
+ .build();
+ }
+
+ @Test
+ void shouldCorrectlyMapAddressEntityToAddressModel() {
+ Address address = this.addressMapper.mapFrom(this.addressEntity);
+
+ assertNotNull(address);
+ assertEquals(ADDRESS_STREET, address.getStreet());
+ assertEquals(ADDRESS_NUMBER, address.getNumber());
+ assertEquals(ADDRESS_NEIGHBORHOOD, address.getNeighborhood());
+ assertEquals(ADDRESS_CITY, address.getCity());
+ assertEquals(ADDRESS_STATE, address.getState());
+ assertEquals(ZIP_CODE, address.getZip());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingNullAddressEntity() {
+ this.addressEntity = null;
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingNullAddressStreet() {
+ this.addressEntity.setStreet(null);
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingEmptyAddressStreet() {
+ this.addressEntity.setStreet(" ");
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingNullAddressNumber() {
+ this.addressEntity.setNumber(null);
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingEmptyAddressNumber() {
+ this.addressEntity.setNumber("");
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingNullAddressNeighborhood() {
+ this.addressEntity.setNeighborhood(null);
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingEmptyAddressNeighborhood() {
+ this.addressEntity.setNeighborhood("");
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingNullAddressCity() {
+ this.addressEntity.setCity(null);
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingEmptyAddressCity() {
+ this.addressEntity.setCity("");
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingNullAddressState() {
+ this.addressEntity.setState(null);
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingEmptyAddressState() {
+ this.addressEntity.setState("");
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingNullAddressZipCode() {
+ this.addressEntity.setZip(null);
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingEmptyAddressZipCode() {
+ this.addressEntity.setZip("");
+
+ AddressEntityFailuresException exception = assertThrows(AddressEntityFailuresException.class, () -> this.addressMapper.mapFrom(this.addressEntity));
+
+ assertNotNull(exception);
+ assertEquals(AddressEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(AddressMapper.ADDRESS_ENTITY_TYPE.getSimpleName())), exception.getMessage());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationEntityMapperTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationEntityMapperTest.java
new file mode 100644
index 0000000..50f7652
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationEntityMapperTest.java
@@ -0,0 +1,53 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.DonationEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@ExtendWith(MockitoExtension.class)
+class DonationEntityMapperTest {
+
+ public static final String DONATION_ID = "28387d3e-e9cc-45b9-b87d-3ee9cc35b912";
+ public static final String DESCRIPTION = "Descricao";
+ public static final int AMOUNT = 1;
+
+
+ private DonationEntityMapper mapper;
+
+ private Donation donation;
+
+ @BeforeEach
+ void setUp() {
+ this.mapper = new DonationEntityMapper();
+ this.donation = new Donation(DONATION_ID, DESCRIPTION, AMOUNT);
+
+ }
+
+ @Test
+ void shouldMapToDonationEntity() {
+
+ DonationEntity donationEntity = this.mapper.mapFrom(this.donation);
+
+ assertNotNull(donationEntity);
+ assertEquals(DONATION_ID, donationEntity.getId());
+ assertEquals(DESCRIPTION, donationEntity.getDescription());
+ assertEquals(AMOUNT, donationEntity.getAmount());
+ }
+
+ @Test
+ void shouldThrowExceptionIfDonationIsNull() {
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.mapper.mapFrom(null));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(Donation.class.getSimpleName())), exception.getMessage());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationMapperTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationMapperTest.java
new file mode 100644
index 0000000..7b91746
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/DonationMapperTest.java
@@ -0,0 +1,126 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.DonationEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.exception.DonationRegisterFailureException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@ExtendWith(MockitoExtension.class)
+class DonationMapperTest {
+
+ public static final String DONATION_ID = "047bcc50-3193-4ef1-bbcc-5031938ef1a5";
+ public static final String DESCRIPTION = "Descricao";
+ public static final int AMOUNT = 1;
+
+
+ private DonationMapper donationMapper;
+
+ private DonationEntity donationEntity;
+
+ @BeforeEach
+ void setUp() {
+ this.donationMapper = new DonationMapper();
+ this.donationEntity = DonationEntity.builder()
+ .id(DONATION_ID)
+ .description(DESCRIPTION)
+ .amount(AMOUNT)
+ .build();
+ }
+
+ @Test
+ void shouldMapFromDonationEntityToDonationWithNegativeAmount() {
+ this.donationEntity.setAmount(-25);
+ Donation donation = this.donationMapper.mapFrom(this.donationEntity);
+
+ assertNotNull(donation);
+ assertEquals(DONATION_ID, donation.getId());
+ assertEquals(DESCRIPTION, donation.getDescription());
+ assertEquals(AMOUNT, donation.getAmount());
+ }
+
+ @Test
+ void shouldMapFromDonationEntityToDonationWithZeroAmount() {
+ this.donationEntity.setAmount(0);
+ Donation donation = this.donationMapper.mapFrom(this.donationEntity);
+
+ assertNotNull(donation);
+ assertEquals(DONATION_ID, donation.getId());
+ assertEquals(DESCRIPTION, donation.getDescription());
+ assertEquals(AMOUNT, donation.getAmount());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenDonationEntityIsNull() {
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.donationMapper.mapFrom(null));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(DonationEntity.class.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenDonationEntityHaveYourIdNull() {
+ this.donationEntity.setId(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.donationMapper.mapFrom(this.donationEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(DonationEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(DonationRegisterFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", "id"})
+ void shouldThrowExceptionWhenDonationEntityHaveYourIdEmptyOrInvalid(String value) {
+ this.donationEntity.setId(value);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.donationMapper.mapFrom(this.donationEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(DonationEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(DonationRegisterFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenDonationEntityHaveYourDescriptionNull() {
+ this.donationEntity.setDescription(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.donationMapper.mapFrom(this.donationEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(DonationEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(DonationRegisterFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenDonationEntityHaveYourDescriptionEmpty() {
+ this.donationEntity.setDescription("");
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.donationMapper.mapFrom(this.donationEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(DonationEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(DonationRegisterFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenDonationEntityHaveYourAmountNull() {
+ this.donationEntity.setAmount(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.donationMapper.mapFrom(this.donationEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(DonationEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(DonationRegisterFailureException.class, exception.getCause().getClass());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterEntityMapperTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterEntityMapperTest.java
new file mode 100644
index 0000000..4ece40c
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterEntityMapperTest.java
@@ -0,0 +1,177 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.ShelterEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.lang.reflect.Field;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@ExtendWith(MockitoExtension.class)
+class ShelterEntityMapperTest {
+
+ public static final String SHELTER_ID = "9f0b9d43-80ec-4399-8b9d-4380ecb399c7";
+ public static final String SHELTER_NAME = "Abrigo";
+
+ public static final String USER_ID = "21f29f51-2c17-458d-b29f-512c17058d97";
+ public static final String USER_NAME = "Usuario";
+ public static final String USER_EMAIL = "email@teste.com";
+ public static final String USER_PASSWORD = "Senha";
+
+ public static final String ADDRESS_ID = "501f97ac-9544-486b-9f97-ac9544486b72";
+ public static final String STREET_NAME = "Rua";
+ public static final String NUMBER = "123";
+ public static final String NEIGHBORHOOD = "Bairro";
+ public static final String CITY = "Cidade";
+ public static final String STATE = "Estado";
+ public static final String ZIP = "91234567";
+
+ public static final String DONATION_ID = "76e97240-2f2b-4a74-a972-402f2b2a74fc";
+ public static final String DONATION_DESCRIPTION = "Doacao";
+ public static final int DONATION_AMOUNT = 1;
+
+
+ private ShelterEntityMapper mapper;
+
+ private Shelter shelter;
+
+ private Donation donation;
+
+ @BeforeEach
+ void setUp() {
+ this.mapper = new ShelterEntityMapper();
+ this.donation = new Donation(DONATION_ID, DONATION_DESCRIPTION, DONATION_AMOUNT);
+ Address address = new Address(ADDRESS_ID, STREET_NAME, NUMBER, NEIGHBORHOOD, CITY, STATE, ZIP);
+ User user = new User(USER_ID, USER_NAME, USER_EMAIL, UserProfile.BENEFICIARY, USER_PASSWORD);
+ this.shelter = new Shelter(SHELTER_ID, SHELTER_NAME, address, user);
+ }
+
+ @Test
+ void shouldMapToShelterEntityWithDonations() {
+ this.shelter.addDonation(this.donation);
+ ShelterEntity shelterEntity = this.mapper.mapFrom(this.shelter);
+
+ assertNotNull(shelterEntity, "Shelter entity should not be null");
+ assertEquals(SHELTER_ID, shelterEntity.getId());
+ assertEquals(SHELTER_NAME, shelterEntity.getShelterName());
+ assertNotNull(shelterEntity.getAddress(), "Address is null");
+ assertEquals(ADDRESS_ID, shelterEntity.getAddress().getId());
+ assertEquals(STREET_NAME, shelterEntity.getAddress().getStreet());
+ assertEquals(NUMBER, shelterEntity.getAddress().getNumber());
+ assertEquals(NEIGHBORHOOD, shelterEntity.getAddress().getNeighborhood());
+ assertEquals(CITY, shelterEntity.getAddress().getCity());
+ assertEquals(STATE, shelterEntity.getAddress().getState());
+ assertEquals(ZIP, shelterEntity.getAddress().getZip());
+ assertNotNull(shelterEntity.getResponsibleUser(), "Responsible user is null");
+ assertEquals(USER_ID, shelterEntity.getResponsibleUser().getId());
+ assertEquals(USER_NAME, shelterEntity.getResponsibleUser().getUserName());
+ assertEquals(USER_EMAIL, shelterEntity.getResponsibleUser().getEmail());
+ assertEquals(UserProfileType.BENEFICIARY, shelterEntity.getResponsibleUser().getUserProfile());
+ assertEquals(USER_PASSWORD, shelterEntity.getResponsibleUser().getUserPassword());
+ assertNotNull(shelterEntity.getDonations(), "donations is null");
+ assertFalse(shelterEntity.getDonations().isEmpty());
+ assertEquals(DONATION_ID, shelterEntity.getDonations().get(0).getId());
+ assertEquals(DONATION_DESCRIPTION, shelterEntity.getDonations().get(0).getDescription());
+ assertEquals(DONATION_AMOUNT, shelterEntity.getDonations().get(0).getAmount());
+ }
+
+ @Test
+ void shouldMapShelterToEntityWithoutDonations() {
+ ShelterEntity shelterEntity = this.mapper.mapFrom(this.shelter);
+
+ assertNotNull(shelterEntity, "Shelter entity should not be null");
+ assertEquals(SHELTER_ID, shelterEntity.getId());
+ assertEquals(SHELTER_NAME, shelterEntity.getShelterName());
+ assertNotNull(shelterEntity.getAddress(), "Address is null");
+ assertEquals(ADDRESS_ID, shelterEntity.getAddress().getId());
+ assertEquals(STREET_NAME, shelterEntity.getAddress().getStreet());
+ assertEquals(NUMBER, shelterEntity.getAddress().getNumber());
+ assertEquals(NEIGHBORHOOD, shelterEntity.getAddress().getNeighborhood());
+ assertEquals(CITY, shelterEntity.getAddress().getCity());
+ assertEquals(STATE, shelterEntity.getAddress().getState());
+ assertEquals(ZIP, shelterEntity.getAddress().getZip());
+ assertNotNull(shelterEntity.getResponsibleUser(), "Responsible user is null");
+ assertEquals(USER_ID, shelterEntity.getResponsibleUser().getId());
+ assertEquals(USER_NAME, shelterEntity.getResponsibleUser().getUserName());
+ assertEquals(USER_EMAIL, shelterEntity.getResponsibleUser().getEmail());
+ assertEquals(UserProfileType.BENEFICIARY, shelterEntity.getResponsibleUser().getUserProfile());
+ assertEquals(USER_PASSWORD, shelterEntity.getResponsibleUser().getUserPassword());
+ assertNotNull(shelterEntity.getDonations(), "donations is null");
+ assertTrue(shelterEntity.getDonations().isEmpty());
+ }
+
+ @Test
+ @SneakyThrows
+ void testMapFromShouldHandleNullDonationsFieldInShelter() {
+
+ Field field = this.shelter.getClass().getDeclaredField("donations");
+ field.setAccessible(true);
+
+ field.set(this.shelter, null);
+
+ ShelterEntity shelterEntity = this.mapper.mapFrom(this.shelter);
+
+ assertNotNull(shelterEntity, "Shelter entity should not be null");
+ assertEquals(SHELTER_ID, shelterEntity.getId());
+ assertEquals(SHELTER_NAME, shelterEntity.getShelterName());
+ assertNotNull(shelterEntity.getAddress(), "Address is null");
+ assertEquals(ADDRESS_ID, shelterEntity.getAddress().getId());
+ assertEquals(STREET_NAME, shelterEntity.getAddress().getStreet());
+ assertEquals(NUMBER, shelterEntity.getAddress().getNumber());
+ assertEquals(NEIGHBORHOOD, shelterEntity.getAddress().getNeighborhood());
+ assertEquals(CITY, shelterEntity.getAddress().getCity());
+ assertEquals(STATE, shelterEntity.getAddress().getState());
+ assertEquals(ZIP, shelterEntity.getAddress().getZip());
+ assertNotNull(shelterEntity.getResponsibleUser(), "Responsible user is null");
+ assertEquals(USER_ID, shelterEntity.getResponsibleUser().getId());
+ assertEquals(USER_NAME, shelterEntity.getResponsibleUser().getUserName());
+ assertEquals(USER_EMAIL, shelterEntity.getResponsibleUser().getEmail());
+ assertEquals(UserProfileType.BENEFICIARY, shelterEntity.getResponsibleUser().getUserProfile());
+ assertEquals(USER_PASSWORD, shelterEntity.getResponsibleUser().getUserPassword());
+ assertNotNull(shelterEntity.getDonations(), "donations is null");
+ assertTrue(shelterEntity.getDonations().isEmpty());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingFromNullShelter() {
+ this.shelter = null;
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.mapper.mapFrom(this.shelter));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntityMapper.SHELTER_CLASS.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ @SneakyThrows
+ void shouldThrowExceptionWhenMappingFromNullShelterResponsibleUser() {
+ Field field = this.shelter.getClass().getDeclaredField("responsibleUser");
+ field.setAccessible(true);
+
+ field.set(this.shelter, null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.mapper.mapFrom(this.shelter));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntityMapper.SHELTER_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserEntityFailuresException.class, exception.getCause().getClass());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterMapperTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterMapperTest.java
new file mode 100644
index 0000000..aea45f8
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/ShelterMapperTest.java
@@ -0,0 +1,245 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.AddressEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.AddressEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.DonationEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.ShelterEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.ShelterContract;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import diegosneves.github.conectardoacoes.core.exception.DonationRegisterFailureException;
+import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+@ExtendWith(MockitoExtension.class)
+class ShelterMapperTest {
+
+ private ShelterMapper shelterMapper;
+
+ private ShelterEntity shelterEntity;
+ private AddressEntity addressEntity;
+ private UserEntity userEntity;
+ private DonationEntity donationEntity;
+
+ @BeforeEach
+ void setUp() {
+ this.shelterMapper = new ShelterMapper();
+
+ this.addressEntity = AddressEntity.builder()
+ .id("0b6a4b56-9a6a-49d4-aa4b-569a6a09d49d")
+ .street("Rua")
+ .number("256")
+ .neighborhood("Bairro")
+ .city("Cidade")
+ .state("Estado")
+ .zip("97110220")
+ .build();
+
+ this.userEntity = UserEntity.builder()
+ .id("60306bda-1ef2-4228-b06b-da1ef26228b1")
+ .userName("Usuario")
+ .email("email@teste.com")
+ .userProfile(UserProfileType.BENEFICIARY)
+ .userPassword("Senha")
+ .build();
+
+ this.donationEntity = DonationEntity.builder()
+ .id("e9bca351-bdbe-4e46-bca3-51bdbe4e464f")
+ .description("Descricao")
+ .amount(10)
+ .build();
+
+ this.shelterEntity = ShelterEntity.builder()
+ .id("5515cf68-f172-4b6f-95cf-68f1725b6f9c")
+ .shelterName("Shelter Entity")
+ .address(this.addressEntity)
+ .responsibleUser(this.userEntity)
+ .donations(List.of(this.donationEntity))
+ .build();
+
+ }
+
+ @Test
+ void shouldMapShelterEntityToShelter() {
+
+ ShelterContract shelter = this.shelterMapper.mapFrom(this.shelterEntity);
+
+ assertNotNull(shelter);
+ assertInstanceOf(Shelter.class, shelter);
+ assertEquals(this.shelterEntity.getShelterName(), shelter.getShelterName());
+ assertEquals(this.shelterEntity.getId(), shelter.getId());
+ assertNotNull(shelter.getAddress());
+ assertEquals(this.addressEntity.getStreet(), shelter.getAddress().getStreet());
+ assertEquals(this.addressEntity.getNumber(), shelter.getAddress().getNumber());
+ assertEquals(this.addressEntity.getNeighborhood(), shelter.getAddress().getNeighborhood());
+ assertEquals(this.addressEntity.getCity(), shelter.getAddress().getCity());
+ assertEquals(this.addressEntity.getState(), shelter.getAddress().getState());
+ assertEquals(this.addressEntity.getZip(), shelter.getAddress().getZip());
+ assertNotNull(shelter.getUser());
+ assertEquals(this.userEntity.getId(), shelter.getUser().getId());
+ assertEquals(this.userEntity.getUserName(), shelter.getUser().getUsername());
+ assertEquals(this.userEntity.getEmail(), shelter.getUser().getEmail());
+ assertEquals(this.userEntity.getUserPassword(), shelter.getUser().getUserPassword());
+ assertNotNull(shelter.getUser().getUserProfile());
+ assertEquals(UserProfile.BENEFICIARY, shelter.getUser().getUserProfile());
+ assertNotNull(shelter.getDonations());
+ assertFalse(shelter.getDonations().isEmpty());
+ assertEquals(this.shelterEntity.getDonations().size(), shelter.getDonations().size());
+ assertEquals(this.donationEntity.getDescription(), shelter.getDonations().get(0).getDescription());
+ assertEquals(this.donationEntity.getAmount(), shelter.getDonations().get(0).getAmount());
+ }
+
+ @Test
+ void shouldCorrectlyMapShelterEntityToShelter() {
+ this.shelterEntity.setDonations(new ArrayList<>());
+
+ ShelterContract shelter = this.shelterMapper.mapFrom(this.shelterEntity);
+
+ assertNotNull(shelter);
+ assertInstanceOf(Shelter.class, shelter);
+ assertEquals(this.shelterEntity.getShelterName(), shelter.getShelterName());
+ assertEquals(this.shelterEntity.getId(), shelter.getId());
+ assertNotNull(shelter.getAddress());
+ assertEquals(this.addressEntity.getStreet(), shelter.getAddress().getStreet());
+ assertEquals(this.addressEntity.getNumber(), shelter.getAddress().getNumber());
+ assertEquals(this.addressEntity.getNeighborhood(), shelter.getAddress().getNeighborhood());
+ assertEquals(this.addressEntity.getCity(), shelter.getAddress().getCity());
+ assertEquals(this.addressEntity.getState(), shelter.getAddress().getState());
+ assertEquals(this.addressEntity.getZip(), shelter.getAddress().getZip());
+ assertNotNull(shelter.getUser());
+ assertEquals(this.userEntity.getId(), shelter.getUser().getId());
+ assertEquals(this.userEntity.getUserName(), shelter.getUser().getUsername());
+ assertEquals(this.userEntity.getEmail(), shelter.getUser().getEmail());
+ assertEquals(this.userEntity.getUserPassword(), shelter.getUser().getUserPassword());
+ assertNotNull(shelter.getUser().getUserProfile());
+ assertEquals(UserProfile.BENEFICIARY, shelter.getUser().getUserProfile());
+ assertNotNull(shelter.getDonations());
+ assertTrue(shelter.getDonations().isEmpty());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenShelterEntityIsNull() {
+ this.shelterEntity = null;
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class,
+ () -> this.shelterMapper.mapFrom(this.shelterEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntity.class.getSimpleName())), exception.getMessage());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", "ID"})
+ void shouldThrowExceptionWhenShelterEntityIdIsEmptyOrInvalid(String id) {
+ this.shelterEntity.setId(id);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class,
+ () -> this.shelterMapper.mapFrom(this.shelterEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(ShelterCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenShelterEntityIdIsNull() {
+ this.shelterEntity.setId(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class,
+ () -> this.shelterMapper.mapFrom(this.shelterEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(ShelterCreationFailureException.class, exception.getCause().getClass());
+ }
+
+
+ @Test
+ void shouldThrowExceptionWhenShelterEntityNameIsEmpty() {
+ this.shelterEntity.setShelterName(" ");
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class,
+ () -> this.shelterMapper.mapFrom(this.shelterEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(ShelterCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenShelterEntityNameIsNull() {
+ this.shelterEntity.setShelterName(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class,
+ () -> this.shelterMapper.mapFrom(this.shelterEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(ShelterCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenShelterEntityAddressIsNull() {
+ this.shelterEntity.setAddress(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class,
+ () -> this.shelterMapper.mapFrom(this.shelterEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(AddressEntityFailuresException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenShelterEntityResponsibleUserIsNull() {
+ this.shelterEntity.setResponsibleUser(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class,
+ () -> this.shelterMapper.mapFrom(this.shelterEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntity.class.getSimpleName())), exception.getMessage());
+ assertEquals(UserEntityFailuresException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenShelterEntityDonationDescriptionIsNull() {
+ this.donationEntity.setDescription(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class,
+ () -> this.shelterMapper.mapFrom(this.shelterEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(Donation.class.getSimpleName())), exception.getMessage());
+ assertEquals(DonationRegisterFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenShelterEntityDonationDescriptionIsEmpty() {
+ this.donationEntity.setDescription(" ");
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class,
+ () -> this.shelterMapper.mapFrom(this.shelterEntity));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(Donation.class.getSimpleName())), exception.getMessage());
+ assertEquals(DonationRegisterFailureException.class, exception.getCause().getClass());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserEntityMapperTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserEntityMapperTest.java
new file mode 100644
index 0000000..a5e0cd0
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserEntityMapperTest.java
@@ -0,0 +1,91 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ConstructorDefaultUndefinedException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.MockedStatic;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+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.Mockito.mockStatic;
+
+@ExtendWith(MockitoExtension.class)
+class UserEntityMapperTest {
+
+ public static final String USER_UUID = "3c489878-c78d-4117-8898-78c78d011708";
+ public static final String USER_NAME = "Usuario";
+ public static final String USER_EMAIL = "email@teste.com";
+ public static final String USER_PASSWORD = "Senha";
+
+ private UserEntityMapper userEntityMapper;
+
+ private User user;
+
+ @BeforeEach
+ void setUp() {
+ this.userEntityMapper = new UserEntityMapper();
+ this.user = new User(USER_UUID, USER_NAME, USER_EMAIL, UserProfile.DONOR, USER_PASSWORD);
+ }
+
+ @Test
+ void shouldCorrectlyMapUserToUserEntity() {
+ UserEntity userEntity = this.userEntityMapper.mapFrom(this.user);
+
+ assertNotNull(userEntity);
+ assertEquals(USER_UUID, userEntity.getId());
+ assertEquals(USER_NAME, userEntity.getUserName());
+ assertEquals(USER_EMAIL, userEntity.getEmail());
+ assertEquals(USER_PASSWORD, userEntity.getUserPassword());
+ assertEquals(UserProfileType.DONOR, userEntity.getUserProfile());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenMappingNullUser() {
+ this.user = null;
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityMapper.mapFrom(this.user));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserEntityMapper.USER_CLASS.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowWhenBuilderMapperFailsToMapUserToUserEntity() {
+
+ try (MockedStatic mockedBuilder = mockStatic(BuilderMapper.class)) {
+
+ mockedBuilder.when(() -> BuilderMapper.mapTo(UserEntity.class, this.user)).thenThrow(ConstructorDefaultUndefinedException.class);
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityMapper.mapFrom(this.user));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserEntityMapper.USER_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(ConstructorDefaultUndefinedException.class, exception.getCause().getClass());
+ }
+ }
+
+ @Test
+ void shouldThrowWhenBuilderMapperFailToMapUserToUserEntity() {
+
+ try (MockedStatic mockedBuilder = mockStatic(BuilderMapper.class)) {
+
+ mockedBuilder.when(() -> BuilderMapper.mapTo(UserEntity.class, this.user)).thenThrow(MapperFailureException.class);
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityMapper.mapFrom(this.user));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserEntityMapper.USER_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(MapperFailureException.class, exception.getCause().getClass());
+ }
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserMapperTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserMapperTest.java
new file mode 100644
index 0000000..c7809ab
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/mapper/UserMapperTest.java
@@ -0,0 +1,172 @@
+package diegosneves.github.conectardoacoes.adapters.rest.mapper;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import diegosneves.github.conectardoacoes.core.exception.UserCreationFailureException;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.junit.jupiter.MockitoExtension;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+@ExtendWith(MockitoExtension.class)
+class UserMapperTest {
+
+ public static final String USER_UUID = "a0b93a5a-be45-4339-b93a-5abe4523393a";
+ public static final String USERNAME = "Usuario";
+ public static final String USER_EMAIL = "email@teste.com";
+ public static final String USER_PASSWORD = "Senha";
+
+ private UserMapper userMapper;
+
+ private UserEntity userEntity;
+
+ @BeforeEach
+ void setUp() {
+ this.userMapper = new UserMapper();
+ this.userEntity = UserEntity.builder()
+ .id(USER_UUID)
+ .userName(USERNAME)
+ .email(USER_EMAIL)
+ .userProfile(UserProfileType.DONOR)
+ .userPassword(USER_PASSWORD)
+ .build();
+ }
+
+ @Test
+ void shouldMapUserEntityToUser() {
+ UserContract user = this.userMapper.mapFrom(this.userEntity);
+
+ assertNotNull(user);
+ assertEquals(USERNAME, user.getUsername());
+ assertEquals(USER_UUID, user.getId());
+ assertEquals(USER_EMAIL, user.getEmail());
+ assertEquals(UserProfile.DONOR, user.getUserProfile());
+ assertEquals(USER_PASSWORD, user.getUserPassword());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserEntityIsNull() {
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(null));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserProfileTypeIsNull() {
+ this.userEntity.setUserProfile(null);
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUsernameIsNull() {
+ this.userEntity.setUserName(null);
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUsernameIsEmpty() {
+ this.userEntity.setUserName(" ");
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserEmailIsNull() {
+ this.userEntity.setEmail(null);
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserEmailIsEmpty() {
+ this.userEntity.setEmail("");
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserPasswordIsNull() {
+ this.userEntity.setUserPassword(null);
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserPasswordIsEmpty() {
+ this.userEntity.setUserPassword(" ");
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserEntityIdIsNull() {
+ this.userEntity.setId(null);
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserEntityIdIsEmpty() {
+ this.userEntity.setId(" ");
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserEntityIdIsInvalid() {
+ this.userEntity.setId("null");
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userMapper.mapFrom(this.userEntity));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserMapper.USER_ENTITY_CLASS.getSimpleName())), exception.getMessage());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/repository/ShelterRepositoryIntegrationTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/repository/ShelterRepositoryIntegrationTest.java
new file mode 100644
index 0000000..42f2a4f
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/repository/ShelterRepositoryIntegrationTest.java
@@ -0,0 +1,410 @@
+package diegosneves.github.conectardoacoes.adapters.rest.repository;
+
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.AddressEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.DonationEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.MapperStrategy;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.ShelterEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.UserEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.model.ShelterEntity;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.ShelterContract;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;
+import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+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;
+
+
+@DataJpaTest
+@ExtendWith(SpringExtension.class)
+class ShelterRepositoryIntegrationTest {
+
+ public static final String ADDRESS_ID = "9f3928bc-3985-4035-b928-bc3985f035c9";
+ public static final String STREET = "Rua";
+ public static final String NUMBER = "123";
+ public static final String NEIGHBORHOOD = "Bairro";
+ public static final String CITY = "Cidade";
+ public static final String STATE = "Estado";
+ public static final String ZIP = "92123456";
+
+ public static final String SHELTER_ID = "1229ed8f-76d3-4fbd-a9ed-8f76d3ffbdf5";
+ public static final String SHELTER_NAME = "Abrigo";
+
+ public static final String USER_ID = "574371b9-ae17-4f07-8371-b9ae175f0721";
+ public static final String USER_NAME = "Fulano";
+ public static final String USER_EMAIL = "email@teste.com";
+ public static final String USER_PASSWORD = "Senha";
+
+ public static final String DONATION_ID = "bf9b8d38-c6b3-4fd6-9b8d-38c6b3bfd69f";
+ public static final String DONATION_DESCRIPTION = "Descrição";
+ public static final int AMOUNT = 1;
+
+ public static final String ENTITY_ID = "b7a89acb-c03f-4f87-a89a-cbc03fef8755";
+
+
+ @Autowired
+ private TestEntityManager entityManager;
+
+ @Autowired
+ private ShelterRepository shelterRepository;
+
+ private Shelter shelter;
+ private Address address;
+ private User user;
+ private Donation donation;
+
+ private ShelterEntity shelterEntity;
+
+ @BeforeEach
+ void setUp() {
+ this.address = new Address(ADDRESS_ID, STREET, NUMBER, NEIGHBORHOOD, CITY, STATE, ZIP);
+ this.user = new User(USER_ID, USER_NAME, USER_EMAIL, UserProfile.DONOR, USER_PASSWORD);
+ this.donation = new Donation(DONATION_ID, DONATION_DESCRIPTION, AMOUNT);
+ this.shelter = new Shelter(SHELTER_ID, SHELTER_NAME, this.address, this.user);
+ }
+
+ private void persistEntity(MapperStrategy mapper, E entity) {
+ this.entityManager.persist(mapper.mapFrom(entity));
+ this.entityManager.flush();
+ }
+
+ private void persistEntity(T entity) {
+ this.entityManager.persist(entity);
+ this.entityManager.flush();
+ }
+
+ @Test
+ void shouldRetrieveAndValidateShelterWithAssociationsIncludingAddressUserAndEmptyDonations() {
+
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(new ShelterEntityMapper(), this.shelter);
+
+ ShelterContract foundShelter = this.shelterRepository.findEntityById(SHELTER_ID);
+
+ assertNotNull(foundShelter);
+ assertEquals(SHELTER_ID, foundShelter.getId());
+ assertEquals(SHELTER_NAME, foundShelter.getShelterName());
+ assertNotNull(foundShelter.getAddress());
+ assertEquals(ADDRESS_ID, foundShelter.getAddress().getId());
+ assertEquals(STREET, foundShelter.getAddress().getStreet());
+ assertEquals(NUMBER, foundShelter.getAddress().getNumber());
+ assertEquals(NEIGHBORHOOD, foundShelter.getAddress().getNeighborhood());
+ assertEquals(CITY, foundShelter.getAddress().getCity());
+ assertEquals(STATE, foundShelter.getAddress().getState());
+ assertEquals(ZIP, foundShelter.getAddress().getZip());
+ assertNotNull(foundShelter.getUser());
+ assertEquals(USER_ID, foundShelter.getUser().getId());
+ assertEquals(USER_NAME, foundShelter.getUser().getUsername());
+ assertEquals(USER_EMAIL, foundShelter.getUser().getEmail());
+ assertEquals(UserProfile.DONOR, foundShelter.getUser().getUserProfile());
+ assertEquals(USER_PASSWORD, foundShelter.getUser().getUserPassword());
+ assertNotNull(foundShelter.getDonations());
+ assertTrue(foundShelter.getDonations().isEmpty());
+ }
+
+ @Test
+ void shouldRetrieveAndValidateShelterWithAssociationsIncludingAddressUserAndNonEmptyDonations() {
+ this.shelter.addDonation(this.donation);
+
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(new ShelterEntityMapper(), this.shelter);
+
+ ShelterContract foundShelter = this.shelterRepository.findEntityById(SHELTER_ID);
+
+ assertNotNull(foundShelter);
+ assertEquals(SHELTER_ID, foundShelter.getId());
+ assertEquals(SHELTER_NAME, foundShelter.getShelterName());
+ assertNotNull(foundShelter.getAddress());
+ assertEquals(ADDRESS_ID, foundShelter.getAddress().getId());
+ assertEquals(STREET, foundShelter.getAddress().getStreet());
+ assertEquals(NUMBER, foundShelter.getAddress().getNumber());
+ assertEquals(NEIGHBORHOOD, foundShelter.getAddress().getNeighborhood());
+ assertEquals(CITY, foundShelter.getAddress().getCity());
+ assertEquals(STATE, foundShelter.getAddress().getState());
+ assertEquals(ZIP, foundShelter.getAddress().getZip());
+ assertNotNull(foundShelter.getUser());
+ assertEquals(USER_ID, foundShelter.getUser().getId());
+ assertEquals(USER_NAME, foundShelter.getUser().getUsername());
+ assertEquals(USER_EMAIL, foundShelter.getUser().getEmail());
+ assertEquals(UserProfile.DONOR, foundShelter.getUser().getUserProfile());
+ assertEquals(USER_PASSWORD, foundShelter.getUser().getUserPassword());
+ assertNotNull(foundShelter.getDonations());
+ assertFalse(foundShelter.getDonations().isEmpty());
+ assertEquals(1, foundShelter.getDonations().size());
+ assertEquals(DONATION_ID, foundShelter.getDonations().get(0).getId());
+ assertEquals(DONATION_DESCRIPTION, foundShelter.getDonations().get(0).getDescription());
+ assertEquals(AMOUNT, foundShelter.getDonations().get(0).getAmount());
+ }
+
+ @Test
+ void shouldRetrieveShelterNull() {
+ this.shelter.addDonation(this.donation);
+
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(new ShelterEntityMapper(), this.shelter);
+
+ ShelterContract foundShelter = this.shelterRepository.findEntityById(ENTITY_ID);
+
+ assertNull(foundShelter);
+ }
+
+ @Test
+ void shouldThrowExceptionWhenFindingEntityByIdGivenNullId() {
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(new ShelterEntityMapper(), this.shelter);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.shelterRepository.findEntityById(null));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterRepository.INVALID_ID_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenFindingEntityByIdGivenEmptyStringId() {
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(new ShelterEntityMapper(), this.shelter);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.shelterRepository.findEntityById(""));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterRepository.INVALID_ID_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionAndHaveCauseWhenFindingEntityByIdGivenInvalidId() {
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(new ShelterEntityMapper(), this.shelter);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.shelterRepository.findEntityById("null"));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterRepository.INVALID_ID_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UuidUtilsException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldRetrieveAllShelterContracts() {
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(new ShelterEntityMapper(), this.shelter);
+
+ List retrievedAll = this.shelterRepository.retrieveAll();
+
+ assertNotNull(retrievedAll);
+ assertFalse(retrievedAll.isEmpty());
+ assertEquals(1, retrievedAll.size());
+ }
+
+ @Test
+ void shouldRetrieveEmptyShelterContractsList() {
+
+ List retrievedAll = this.shelterRepository.retrieveAll();
+
+ assertNotNull(retrievedAll);
+ assertTrue(retrievedAll.isEmpty());
+ }
+
+ @Test
+ @SneakyThrows
+ void shouldReturnEmptyListWhenMapEntityListInvokedWithNull() {
+ Method method = ShelterRepository.class.getDeclaredMethod("mapEntityList", List.class);
+ method.setAccessible(true);
+
+ List result = (List) method.invoke(this.shelterRepository, new Object[]{null});
+ assertNotNull(result);
+ assertTrue(result.isEmpty());
+ }
+
+ @Test
+ void shouldThrowExceptionOnRetrieveAllWithInvalidShelterEntity() {
+ this.shelterEntity = new ShelterEntityMapper().mapFrom(this.shelter);
+ this.shelterEntity.setShelterName("");
+
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(this.shelterEntity);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.shelterRepository.retrieveAll());
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(ShelterEntity.class.getSimpleName())), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(ShelterCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldPersistAndValidateShelterIncludingAssociationsWithoutDonations() {
+
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+
+ ShelterContract persisted = this.shelterRepository.persist(this.shelter);
+
+ assertNotNull(persisted);
+ assertEquals(SHELTER_ID, persisted.getId());
+ assertEquals(SHELTER_NAME, persisted.getShelterName());
+ assertNotNull(persisted.getAddress());
+ assertEquals(ADDRESS_ID, persisted.getAddress().getId());
+ assertEquals(STREET, persisted.getAddress().getStreet());
+ assertEquals(NUMBER, persisted.getAddress().getNumber());
+ assertEquals(NEIGHBORHOOD, persisted.getAddress().getNeighborhood());
+ assertEquals(CITY, persisted.getAddress().getCity());
+ assertEquals(STATE, persisted.getAddress().getState());
+ assertEquals(ZIP, persisted.getAddress().getZip());
+ assertNotNull(persisted.getUser());
+ assertEquals(USER_ID, persisted.getUser().getId());
+ assertEquals(USER_NAME, persisted.getUser().getUsername());
+ assertEquals(USER_EMAIL, persisted.getUser().getEmail());
+ assertEquals(UserProfile.DONOR, persisted.getUser().getUserProfile());
+ assertEquals(USER_PASSWORD, persisted.getUser().getUserPassword());
+ assertNotNull(persisted.getDonations());
+ assertTrue(persisted.getDonations().isEmpty());
+ }
+
+ @Test
+ void shouldPersistAndValidateShelterIncludingAssociationsWithDonations() {
+ this.shelterEntity = new ShelterEntityMapper().mapFrom(this.shelter);
+
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(this.shelterEntity);
+
+ ShelterContract found = this.shelterRepository.findEntityById(SHELTER_ID);
+
+ found.addDonation(this.donation);
+
+ ShelterContract persisted = this.shelterRepository.persist(found);
+
+ assertNotNull(persisted);
+ assertEquals(SHELTER_ID, persisted.getId());
+ assertEquals(SHELTER_NAME, persisted.getShelterName());
+ assertNotNull(persisted.getAddress());
+ assertEquals(ADDRESS_ID, persisted.getAddress().getId());
+ assertEquals(STREET, persisted.getAddress().getStreet());
+ assertEquals(NUMBER, persisted.getAddress().getNumber());
+ assertEquals(NEIGHBORHOOD, persisted.getAddress().getNeighborhood());
+ assertEquals(CITY, persisted.getAddress().getCity());
+ assertEquals(STATE, persisted.getAddress().getState());
+ assertEquals(ZIP, persisted.getAddress().getZip());
+ assertNotNull(persisted.getUser());
+ assertEquals(USER_ID, persisted.getUser().getId());
+ assertEquals(USER_NAME, persisted.getUser().getUsername());
+ assertEquals(USER_EMAIL, persisted.getUser().getEmail());
+ assertEquals(UserProfile.DONOR, persisted.getUser().getUserProfile());
+ assertEquals(USER_PASSWORD, persisted.getUser().getUserPassword());
+ assertNotNull(persisted.getDonations());
+ assertFalse(persisted.getDonations().isEmpty());
+ assertEquals(1, persisted.getDonations().size());
+ assertEquals(DONATION_ID, persisted.getDonations().get(0).getId());
+ assertEquals(DONATION_DESCRIPTION, persisted.getDonations().get(0).getDescription());
+ assertEquals(AMOUNT, persisted.getDonations().get(0).getAmount());
+ }
+
+ @Test
+ void shouldThrowShelterEntityFailuresExceptionWhenPersistNullEntity() {
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.shelterRepository.persist(null));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterRepository.SHELTER_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldDeleteShelterEntityAndConfirmItsDeletion() {
+
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(new ShelterEntityMapper(), this.shelter);
+
+ this.shelterRepository.deleteEntityById(SHELTER_ID);
+
+ assertNull(this.shelterRepository.findById(SHELTER_ID).orElse(null));
+ }
+
+ @Test
+ void shouldHandleNonExistentEntityDeletionAttemptGracefully() {
+
+ persistEntity(new AddressEntityMapper(), this.address);
+ persistEntity(new UserEntityMapper(), this.user);
+ persistEntity(new DonationEntityMapper(), this.donation);
+ persistEntity(new ShelterEntityMapper(), this.shelter);
+
+ this.shelterRepository.deleteEntityById(ENTITY_ID);
+
+ assertNull(this.shelterRepository.findById(ENTITY_ID).orElse(null));
+ }
+
+ @Test
+ void shouldThrowExceptionWhenIdIsEmpty() {
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.shelterRepository.deleteEntityById(""));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterRepository.INVALID_ID_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenIdIsNull() {
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.shelterRepository.deleteEntityById(null));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterRepository.INVALID_ID_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenIdIsInvalid() {
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.shelterRepository.deleteEntityById("null"));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterRepository.INVALID_ID_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UuidUtilsException.class, exception.getCause().getClass());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/repository/UserRepositoryTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/repository/UserRepositoryTest.java
new file mode 100644
index 0000000..db504e2
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/repository/UserRepositoryTest.java
@@ -0,0 +1,261 @@
+package diegosneves.github.conectardoacoes.adapters.rest.repository;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.MapperFailureException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.MapperStrategy;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.UserEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import diegosneves.github.conectardoacoes.core.exception.UserCreationFailureException;
+import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
+import lombok.SneakyThrows;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
+import org.springframework.boot.test.autoconfigure.orm.jpa.TestEntityManager;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+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;
+
+@DataJpaTest
+@ExtendWith(SpringExtension.class)
+class UserRepositoryTest {
+
+ public static final String USER_ID = "574371b9-ae17-4f07-8371-b9ae175f0721";
+ public static final String USER_NAME = "Fulano";
+ public static final String USER_EMAIL = "email@teste.com";
+ public static final String USER_PASSWORD = "Senha";
+
+ @Autowired
+ private TestEntityManager entityManager;
+
+ @Autowired
+ private UserRepository repository;
+
+ private User user;
+
+ @BeforeEach
+ void setUp() {
+ this.user = new User(USER_ID, USER_NAME, USER_EMAIL, UserProfile.DONOR, USER_PASSWORD);
+ }
+
+ private void persistEntity(MapperStrategy mapper, E entity) {
+ this.entityManager.persist(mapper.mapFrom(entity));
+ this.entityManager.flush();
+ }
+
+ private void persistEntity(T entity) {
+ this.entityManager.persist(entity);
+ this.entityManager.flush();
+ }
+
+ @Test
+ void shouldFindUserByEmail() {
+
+ this.persistEntity(new UserEntityMapper(), this.user);
+
+ Optional foundUser = this.repository.findByEmail(USER_EMAIL);
+
+ assertFalse(foundUser.isEmpty());
+ UserEntity foundUserEntity = foundUser.get();
+ assertEquals(USER_ID, foundUserEntity.getId());
+ assertEquals(USER_NAME, foundUserEntity.getUserName());
+ assertEquals(USER_EMAIL, foundUserEntity.getEmail());
+ assertEquals(UserProfileType.DONOR, foundUserEntity.getUserProfile());
+ assertEquals(USER_PASSWORD, foundUserEntity.getUserPassword());
+ }
+
+ @Test
+ void shouldNotFindUserByEmail() {
+
+ this.persistEntity(new UserEntityMapper(), this.user);
+
+ Optional foundUser = this.repository.findByEmail("teste@email.com");
+
+ assertTrue(foundUser.isEmpty());
+ }
+
+ @Test
+ void shouldReturnUserWhenUserExistsInRepository() {
+ this.persistEntity(new UserEntityMapper(), this.user);
+
+ UserContract foundUser = this.repository.findEntityById(USER_ID);
+
+ assertNotNull(foundUser);
+ assertEquals(USER_ID, foundUser.getId());
+ assertEquals(USER_NAME, foundUser.getUsername());
+ assertEquals(USER_EMAIL, foundUser.getEmail());
+ assertEquals(UserProfile.DONOR, foundUser.getUserProfile());
+ assertEquals(USER_PASSWORD, foundUser.getUserPassword());
+ }
+
+ @Test
+ void shouldReturnNullWhenUserDoesNotExistInRepository() {
+ UserContract foundUser = this.repository.findEntityById(USER_ID);
+
+ assertNull(foundUser);
+ }
+
+ @Test
+ void verifyExceptionThrownWhenInvalidIdIsProviedToFindEntityById() {
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.repository.findEntityById("USER_ID"));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserRepository.USER_ID_ERROR_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UuidUtilsException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " "})
+ void verifyExceptionThrownWhenEmptyIdIsProvidedToFindEntityById(String value) {
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.repository.findEntityById(value));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserRepository.USER_ID_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void verifyExceptionThrownWhenNullIdIsProvidedToFindEntityById() {
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.repository.findEntityById(null));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserRepository.USER_ID_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldRetrieveUserContract() {
+ this.persistEntity(new UserEntityMapper(), this.user);
+
+ List userContracts = this.repository.retrieveAll();
+
+ assertNotNull(userContracts);
+ assertFalse(userContracts.isEmpty());
+ assertEquals(1, userContracts.size());
+ }
+
+ @Test
+ void shouldReturnEmptyListWhenNoUsersPersisted() {
+ List userContracts = this.repository.retrieveAll();
+
+ assertNotNull(userContracts);
+ assertTrue(userContracts.isEmpty());
+ }
+
+ @Test
+ @SneakyThrows
+ void shouldReturnEmptyListWhenNullPassedToMapEntityList() {
+ Method method = UserRepository.class.getDeclaredMethod("mapEntityList", List.class);
+ method.setAccessible(true);
+
+ List userContracts = (List) method.invoke(this.repository, new Object[]{null});
+
+ assertNotNull(userContracts);
+ assertTrue(userContracts.isEmpty());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUsernameIsNull() {
+ UserEntity userEntity = new UserEntityMapper().mapFrom(this.user);
+ userEntity.setUserName(null);
+ this.persistEntity(userEntity);
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.repository.retrieveAll());
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(MapperFailureException.ERROR.formatErrorMessage(UserEntity.class.getSimpleName())), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldPersistAndRetrieveUserAttributesCorrectly() {
+ UserContract persisted = this.repository.persist(this.user);
+
+ assertNotNull(persisted);
+ assertEquals(USER_ID, persisted.getId());
+ assertEquals(USER_NAME, persisted.getUsername());
+ assertEquals(USER_EMAIL, persisted.getEmail());
+ assertEquals(UserProfile.DONOR, persisted.getUserProfile());
+ assertEquals(USER_PASSWORD, persisted.getUserPassword());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenPersistNullUser() {
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.repository.persist(null));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserRepository.REQUIRED_USER_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldDeleteUserEntityCorrectly() {
+ this.persistEntity(new UserEntityMapper(), this.user);
+
+ this.repository.deleteEntityById(USER_ID);
+
+ assertNull(this.repository.findById(USER_ID).orElse(null));
+ }
+
+ @Test
+ void shouldNotAffectDatabaseWhenAttemptToDeleteNonExistingUserEntity() {
+ this.persistEntity(new UserEntityMapper(), this.user);
+ String uuidNonexistent = "777e9377-526d-402c-be93-77526d402cd3";
+
+ this.repository.deleteEntityById(uuidNonexistent);
+
+ assertNull(this.repository.findById(uuidNonexistent).orElse(null));
+ assertNotNull(this.repository.findById(USER_ID).orElse(null));
+ }
+
+ @Test
+ void shouldThrowExceptionWhenDeletingEntityWithNullId() {
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.repository.deleteEntityById(null));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserRepository.USER_ID_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " "})
+ void shouldThrowExceptionWhenDeletingEntityWithInvalidId(String id) {
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.repository.deleteEntityById(id));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserRepository.USER_ID_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenDeletingEntityWithNullIdAndCatchUuidException() {
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.repository.deleteEntityById("null"));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserRepository.USER_ID_ERROR_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UuidUtilsException.class, exception.getCause().getClass());
+ }
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/ShelterEntityServiceImplTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/ShelterEntityServiceImplTest.java
new file mode 100644
index 0000000..fd737b9
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/ShelterEntityServiceImplTest.java
@@ -0,0 +1,475 @@
+package diegosneves.github.conectardoacoes.adapters.rest.service.impl;
+
+import diegosneves.github.conectardoacoes.adapters.rest.dto.AddressDTO;
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.ShelterEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.AddressEntityMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.mapper.BuilderMapper;
+import diegosneves.github.conectardoacoes.adapters.rest.model.AddressEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.model.DonationEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.repository.AddressRepository;
+import diegosneves.github.conectardoacoes.adapters.rest.repository.DonationRepository;
+import diegosneves.github.conectardoacoes.adapters.rest.repository.ShelterRepository;
+import diegosneves.github.conectardoacoes.adapters.rest.request.ShelterCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.ShelterCreatedResponse;
+import diegosneves.github.conectardoacoes.adapters.rest.service.UserEntityService;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.Shelter;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.ShelterContract;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
+import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import diegosneves.github.conectardoacoes.core.exception.AddressCreationFailureException;
+import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;
+import diegosneves.github.conectardoacoes.core.utils.UuidUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockedStatic;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+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.assertThrows;
+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.mockStatic;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(SpringExtension.class)
+class ShelterEntityServiceImplTest {
+
+ public static final String SHELTER_ID = "1229ed8f-76d3-4fbd-a9ed-8f76d3ffbdf5";
+ public static final String SHELTER_NAME = "Abrigo";
+
+ public static final String USER_ID = "574371b9-ae17-4f07-8371-b9ae175f0721";
+ public static final String USER_NAME = "Fulano";
+ public static final String USER_EMAIL = "email@email.com";
+ public static final String USER_PASSWORD = "Senha";
+
+ public static final String ADDRESS_ID = "9f3928bc-3985-4035-b928-bc3985f035c9";
+ public static final String STREET = "Rua";
+ public static final String NUMBER = "298";
+ public static final String NEIGHBORHOOD = "Bairro";
+ public static final String CITY = "Cidade";
+ public static final String STATE = "Estado";
+ public static final String ZIP = "98456123";
+
+ public static final String DONATION_ID = "bf9b8d38-c6b3-4fd6-9b8d-38c6b3bfd69f";
+ public static final String DONATION_DESCRIPTION = "Descrição";
+ public static final int AMOUNT = 1;
+
+ public static final String ENTITY_ID = "b7a89acb-c03f-4f87-a89a-cbc03fef8755";
+
+
+ @InjectMocks
+ private ShelterEntityServiceImpl service;
+
+ @Mock
+ private ShelterRepository repository;
+
+ @Mock
+ private UserEntityService userEntityService;
+
+ @Mock
+ private DonationRepository donationRepository;
+
+ @Mock
+ private AddressRepository addressRepository;
+
+ @Captor
+ private ArgumentCaptor shelterCaptor;
+
+ @Captor
+ private ArgumentCaptor addressCaptor;
+
+ private ShelterCreationRequest request;
+ private AddressDTO addressDTO;
+ private User user;
+ private Shelter shelter;
+ private Address address;
+ private Donation donation;
+
+ @BeforeEach
+ void setUp() {
+ this.addressDTO = AddressDTO.builder()
+ .street(STREET)
+ .number(NUMBER)
+ .neighborhood(NEIGHBORHOOD)
+ .city(CITY)
+ .state(STATE)
+ .zip(ZIP)
+ .build();
+
+ this.request = ShelterCreationRequest.builder()
+ .shelterName(SHELTER_NAME)
+ .address(this.addressDTO)
+ .responsibleUserEmail(USER_EMAIL)
+ .build();
+
+ this.address = new Address(ADDRESS_ID, STREET, NUMBER, NEIGHBORHOOD, CITY, STATE, ZIP);
+ this.user = new User(USER_ID, USER_NAME, USER_EMAIL, UserProfile.DONOR, USER_PASSWORD);
+ this.donation = new Donation(DONATION_ID, DONATION_DESCRIPTION, AMOUNT);
+ this.shelter = new Shelter(SHELTER_ID, SHELTER_NAME, this.address, this.user);
+ }
+
+ @Test
+ void shouldCreateShelter() {
+ AddressEntity addressEntity = new AddressEntityMapper().mapFrom(this.address);
+ when(this.userEntityService.searchUserByEmail(USER_EMAIL)).thenReturn(this.user);
+ when(this.addressRepository.save(any(AddressEntity.class))).thenReturn(addressEntity);
+ when(this.repository.persist(any(ShelterContract.class))).thenReturn(this.shelter);
+
+ ShelterCreatedResponse response = this.service.createShelter(this.request);
+
+ verify(this.userEntityService, times(1)).searchUserByEmail(USER_EMAIL);
+ verify(this.addressRepository, times(1)).save(addressCaptor.capture());
+ verify(this.repository, times(1)).persist(shelterCaptor.capture());
+ verify(this.donationRepository, never()).save(any(DonationEntity.class));
+
+ assertNotNull(response);
+ assertEquals(SHELTER_ID, response.getId());
+ assertEquals(SHELTER_NAME, response.getShelterName());
+ assertEquals(STREET, response.getAddress().getStreet());
+ assertEquals(NUMBER, response.getAddress().getNumber());
+ assertEquals(NEIGHBORHOOD, response.getAddress().getNeighborhood());
+ assertEquals(CITY, response.getAddress().getCity());
+ assertEquals(STATE, response.getAddress().getState());
+ assertEquals(ZIP, response.getAddress().getZip());
+ assertEquals(USER_ID, response.getResponsibleUser().getId());
+ assertEquals(USER_NAME, response.getResponsibleUser().getUserName());
+ assertEquals(USER_EMAIL, response.getResponsibleUser().getEmail());
+ assertNotNull(response.getResponsibleUser().getUserProfile());
+ assertEquals(UserProfileType.DONOR, response.getResponsibleUser().getUserProfile());
+ assertNotNull(shelterCaptor.getValue());
+ assertTrue(UuidUtils.isValidUUID(shelterCaptor.getValue().getId()));
+ assertEquals(SHELTER_NAME, shelterCaptor.getValue().getShelterName());
+ assertNotNull(shelterCaptor.getValue().getDonations());
+ assertTrue(shelterCaptor.getValue().getDonations().isEmpty());
+ assertNotNull(shelterCaptor.getValue().getAddress());
+ assertNotNull(addressCaptor.getValue());
+ assertTrue(UuidUtils.isValidUUID(addressCaptor.getValue().getId()));
+ assertEquals(STREET, shelterCaptor.getValue().getAddress().getStreet());
+ assertEquals(NUMBER, shelterCaptor.getValue().getAddress().getNumber());
+ assertEquals(NEIGHBORHOOD, shelterCaptor.getValue().getAddress().getNeighborhood());
+ assertEquals(CITY, shelterCaptor.getValue().getAddress().getCity());
+ assertEquals(STATE, shelterCaptor.getValue().getAddress().getState());
+ assertEquals(ZIP, shelterCaptor.getValue().getAddress().getZip());
+ assertNotNull(shelterCaptor.getValue().getUser());
+ assertTrue(UuidUtils.isValidUUID(shelterCaptor.getValue().getUser().getId()));
+ assertEquals(USER_NAME, shelterCaptor.getValue().getUser().getUsername());
+ assertEquals(USER_EMAIL, shelterCaptor.getValue().getUser().getEmail());
+ assertEquals(UserProfile.DONOR, shelterCaptor.getValue().getUser().getUserProfile());
+ assertEquals(USER_PASSWORD, shelterCaptor.getValue().getUser().getUserPassword());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " "})
+ void shouldThrowExceptionWhenShelterNameIsBlank(String shelterName) {
+ this.request.setShelterName(shelterName);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.SHELTER_CREATION_ERROR_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(ShelterCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenShelterNameIsNull() {
+ this.request.setShelterName(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.SHELTER_CREATION_ERROR_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(ShelterCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoIsNullInCreateShelter() {
+ this.request.setAddress(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoStreetNameIsNullInCreateShelter() {
+ this.addressDTO.setStreet(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", ""})
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoStreetNameIsBlankInCreateShelter(String addressStreet) {
+ this.addressDTO.setStreet(addressStreet);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoNumberIsNullInCreateShelter() {
+ this.addressDTO.setNumber(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", ""})
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoNumberIsBlankInCreateShelter(String value) {
+ this.addressDTO.setNumber(value);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoNeighborhoodIsNullInCreateShelter() {
+ this.addressDTO.setNeighborhood(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", ""})
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoNeighborhoodIsBlankInCreateShelter(String value) {
+ this.addressDTO.setNeighborhood(value);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoCityIsNullInCreateShelter() {
+ this.addressDTO.setCity(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", ""})
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoCityIsBlankInCreateShelter(String value) {
+ this.addressDTO.setCity(value);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoStateIsNullInCreateShelter() {
+ this.addressDTO.setState(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", ""})
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoStateIsBlankInCreateShelter(String value) {
+ this.addressDTO.setState(value);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoZipCodeIsNullInCreateShelter() {
+ this.addressDTO.setZip(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", ""})
+ void shouldThrowShelterEntityFailuresExceptionWhenAddressDtoZipCodeIsBlankInCreateShelter(String value) {
+ this.addressDTO.setZip(value);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ADDRESS_CREATION_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(AddressCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " "})
+ void shouldThrowExceptionWhenResponsibleUserEmailIsBlank(String value) {
+ this.request.setResponsibleUserEmail(value);
+ when(this.userEntityService.searchUserByEmail(anyString())).thenThrow(UserEntityFailuresException.class);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.USER_RESPONSIBLE_EMAIL_NOT_FOUND_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UserEntityFailuresException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenResponsibleUserEmailIsNull() {
+ this.request.setResponsibleUserEmail(null);
+ when(this.userEntityService.searchUserByEmail(null)).thenThrow(UserEntityFailuresException.class);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.USER_RESPONSIBLE_EMAIL_NOT_FOUND_ERROR), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UserEntityFailuresException.class, exception.getCause().getClass());
+ }
+
+
+ @Test
+ void mapAddressAndSaveToRepositoryThrowsExceptionWhenAddressIsNull() {
+
+ try (MockedStatic mockedBuilder = mockStatic(BuilderMapper.class)) {
+
+ mockedBuilder.when(() -> BuilderMapper.mapTo(any(AddressEntityMapper.class), any(Address.class))).thenThrow(IllegalArgumentException.class);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.addressRepository, never()).save(any(AddressEntity.class));
+ verify(this.repository, never()).persist(any(ShelterContract.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.ERROR_MAPPING_ADDRESS), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(IllegalArgumentException.class, exception.getCause().getClass());
+ }
+ }
+
+ @Test
+ void mapShelterAndSaveToRepositoryThrowsExceptionWhenAddressIsNull() {
+
+ when(this.userEntityService.searchUserByEmail(anyString())).thenReturn(this.user);
+ when(this.repository.persist(any(ShelterContract.class))).thenReturn(null);
+
+ ShelterEntityFailuresException exception = assertThrows(ShelterEntityFailuresException.class, () -> this.service.createShelter(this.request));
+
+ verify(this.addressRepository, times(1)).save(any(AddressEntity.class));
+ verify(this.repository, times(1)).persist(any(ShelterContract.class));
+
+ assertNotNull(exception);
+ assertEquals(ShelterEntityFailuresException.ERROR.formatErrorMessage(ShelterEntityServiceImpl.SHELTER_CREATION_ERROR_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(IllegalArgumentException.class, exception.getCause().getClass());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/UserEntityServiceImplTest.java b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/UserEntityServiceImplTest.java
new file mode 100644
index 0000000..999d3a7
--- /dev/null
+++ b/src/test/java/diegosneves/github/conectardoacoes/adapters/rest/service/impl/UserEntityServiceImplTest.java
@@ -0,0 +1,294 @@
+package diegosneves.github.conectardoacoes.adapters.rest.service.impl;
+
+import diegosneves.github.conectardoacoes.adapters.rest.enums.UserProfileType;
+import diegosneves.github.conectardoacoes.adapters.rest.exception.UserEntityFailuresException;
+import diegosneves.github.conectardoacoes.adapters.rest.model.UserEntity;
+import diegosneves.github.conectardoacoes.adapters.rest.repository.UserRepository;
+import diegosneves.github.conectardoacoes.adapters.rest.request.UserEntityCreationRequest;
+import diegosneves.github.conectardoacoes.adapters.rest.response.UserEntityCreatedResponse;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
+import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
+import diegosneves.github.conectardoacoes.core.exception.UserCreationFailureException;
+import diegosneves.github.conectardoacoes.core.utils.UuidUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.util.Optional;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@ExtendWith(SpringExtension.class)
+class UserEntityServiceImplTest {
+
+ public static final String USER_ID = "f5f3c02d-2863-46a0-b3c0-2d286336a0a2";
+ public static final String USERNAME = "Fulano";
+ public static final String USER_EMAIL = "email@test.com";
+ public static final String USER_PASSWORD = "Senha";
+
+
+ @InjectMocks
+ private UserEntityServiceImpl userEntityService;
+
+ @Mock
+ private UserRepository userRepository;
+
+ @Captor
+ private ArgumentCaptor userEntityCaptor;
+
+ private UserEntity userEntity;
+ private UserEntityCreationRequest request;
+
+ @BeforeEach
+ void setUp() {
+ this.userEntity = UserEntity.builder()
+ .id(USER_ID)
+ .userName(USERNAME)
+ .email(USER_EMAIL)
+ .userProfile(UserProfileType.BENEFICIARY)
+ .userPassword(USER_PASSWORD)
+ .build();
+
+ this.request = UserEntityCreationRequest.builder()
+ .userName(USERNAME)
+ .email(USER_EMAIL)
+ .userProfile(UserProfileType.DONOR)
+ .userPassword(USER_PASSWORD)
+ .build();
+ }
+
+ @Test
+ void shouldReturnUserEntityByEmail() {
+ when(this.userRepository.findByEmail(USER_EMAIL)).thenReturn(Optional.ofNullable(this.userEntity));
+
+ User entity = (User) this.userEntityService.searchUserByEmail("email@test.com");
+
+ verify(this.userRepository, times(1)).findByEmail(anyString());
+
+ assertNotNull(entity);
+ assertEquals(USER_ID, entity.getId());
+ assertEquals(USERNAME, entity.getUsername());
+ assertEquals(USER_EMAIL, entity.getEmail());
+ assertEquals(UserProfile.BENEFICIARY, entity.getUserProfile());
+ assertEquals(USER_PASSWORD, entity.getUserPassword());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenUserNotFound() {
+ String email = "email@teste.com";
+ when(this.userRepository.findByEmail(USER_EMAIL)).thenReturn(Optional.ofNullable(this.userEntity));
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.searchUserByEmail(email));
+
+ verify(this.userRepository, times(1)).findByEmail(anyString());
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(String.format(UserEntityServiceImpl.EMAIL_NOT_FOUND_ERROR_MESSAGE, email)), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenEmailIsEmpty() {
+ String email = "";
+ when(this.userRepository.findByEmail(USER_EMAIL)).thenReturn(Optional.ofNullable(this.userEntity));
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.searchUserByEmail(email));
+
+ verify(this.userRepository, never()).findByEmail(anyString());
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.INVALID_EMAIL_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenEmailIsNull() {
+ when(this.userRepository.findByEmail(USER_EMAIL)).thenReturn(Optional.ofNullable(this.userEntity));
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.searchUserByEmail(null));
+
+ verify(this.userRepository, never()).findByEmail(anyString());
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.INVALID_EMAIL_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldCreateUserEntity() {
+ this.userEntity.setUserProfile(UserProfileType.DONOR);
+ when(this.userRepository.findByEmail(USER_EMAIL)).thenReturn(Optional.empty());
+ when(this.userRepository.save(any(UserEntity.class))).thenReturn(this.userEntity);
+
+ UserEntityCreatedResponse actual = this.userEntityService.createUserEntity(this.request);
+
+ verify(this.userRepository, times(1)).findByEmail(USER_EMAIL);
+ verify(this.userRepository, times(1)).save(this.userEntityCaptor.capture());
+
+ assertNotNull(actual);
+ UserEntity captorValue = this.userEntityCaptor.getValue();
+ assertNotNull(captorValue);
+ assertTrue(UuidUtils.isValidUUID(captorValue.getId()));
+ assertEquals(USERNAME, captorValue.getUserName());
+ assertEquals(USER_EMAIL, captorValue.getEmail());
+ assertEquals(USER_PASSWORD, captorValue.getUserPassword());
+ assertEquals(UserProfileType.DONOR, captorValue.getUserProfile());
+ assertEquals(USER_ID, actual.getId());
+ assertEquals(USERNAME, actual.getUserName());
+ assertEquals(USER_EMAIL, actual.getEmail());
+ assertEquals(UserProfileType.DONOR, actual.getUserProfile());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenEmailAlreadyExists() {
+ when(this.userRepository.findByEmail(USER_EMAIL)).thenReturn(Optional.ofNullable(this.userEntity));
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.createUserEntity(this.request));
+
+ verify(this.userRepository, times(1)).findByEmail(USER_EMAIL);
+ verify(this.userRepository, never()).save(any(UserEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.EMAIL_ALREADY_IN_USE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenRequestUserEmailIsNull() {
+ this.request.setEmail(null);
+ when(this.userRepository.findByEmail(anyString())).thenReturn(Optional.empty());
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.createUserEntity(this.request));
+
+ verify(this.userRepository, never()).findByEmail(anyString());
+ verify(this.userRepository, never()).save(any(UserEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.INVALID_EMAIL_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " "})
+ void shouldThrowExceptionWhenRequestUserEmailIsBlank(String requestUserEmail) {
+ this.request.setEmail(requestUserEmail);
+ when(this.userRepository.findByEmail(anyString())).thenReturn(Optional.empty());
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.createUserEntity(this.request));
+
+ verify(this.userRepository, never()).findByEmail(anyString());
+ verify(this.userRepository, never()).save(any(UserEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.INVALID_EMAIL_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenRequestUsernameIsNull() {
+ this.request.setUserName(null);
+ when(this.userRepository.findByEmail(anyString())).thenReturn(Optional.empty());
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.createUserEntity(this.request));
+
+ verify(this.userRepository, times(1)).findByEmail(anyString());
+ verify(this.userRepository, never()).save(any(UserEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.USER_CREATION_FAILURE_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " "})
+ void shouldThrowExceptionWhenRequestUsernameIsBlank(String requestUserValue) {
+ this.request.setUserName(requestUserValue);
+ when(this.userRepository.findByEmail(anyString())).thenReturn(Optional.empty());
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.createUserEntity(this.request));
+
+ verify(this.userRepository, times(1)).findByEmail(anyString());
+ verify(this.userRepository, never()).save(any(UserEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.USER_CREATION_FAILURE_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenRequestUserPasswordIsNull() {
+ this.request.setUserPassword(null);
+ when(this.userRepository.findByEmail(anyString())).thenReturn(Optional.empty());
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.createUserEntity(this.request));
+
+ verify(this.userRepository, times(1)).findByEmail(anyString());
+ verify(this.userRepository, never()).save(any(UserEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.USER_CREATION_FAILURE_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"", " "})
+ void shouldThrowExceptionWhenRequestUserPasswordIsBlank(String requestUserValue) {
+ this.request.setUserPassword(requestUserValue);
+ when(this.userRepository.findByEmail(anyString())).thenReturn(Optional.empty());
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.createUserEntity(this.request));
+
+ verify(this.userRepository, times(1)).findByEmail(anyString());
+ verify(this.userRepository, never()).save(any(UserEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.USER_CREATION_FAILURE_MESSAGE), exception.getMessage());
+ assertNotNull(exception.getCause());
+ assertEquals(UserCreationFailureException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenRequestUserProfileIsNull() {
+ this.request.setUserProfile(null);
+ when(this.userRepository.findByEmail(anyString())).thenReturn(Optional.empty());
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.createUserEntity(this.request));
+
+ verify(this.userRepository, times(1)).findByEmail(anyString());
+ verify(this.userRepository, never()).save(any(UserEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.USER_PROFILE_VALIDATION_FAILURE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+ @Test
+ void shouldThrowExceptionWhenRequestIsNull() {
+
+ UserEntityFailuresException exception = assertThrows(UserEntityFailuresException.class, () -> this.userEntityService.createUserEntity(null));
+
+ verify(this.userRepository, never()).findByEmail(anyString());
+ verify(this.userRepository, never()).save(any(UserEntity.class));
+
+ assertNotNull(exception);
+ assertEquals(UserEntityFailuresException.ERROR.formatErrorMessage(UserEntityServiceImpl.MISSING_USER_ENTITY_REQUEST_ERROR_MESSAGE), exception.getMessage());
+ assertNull(exception.getCause());
+ }
+
+}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/ShelterTest.java b/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/ShelterTest.java
index 53ce521..93e9582 100644
--- a/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/ShelterTest.java
+++ b/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/ShelterTest.java
@@ -26,6 +26,9 @@ class ShelterTest {
private static final String UUID_TEST = "4658a51c-3840-453e-bc69-e2b4cff191a4";
public static final String UUID_ERROR_MESSAGE = "UUID deve ser informado";
+ public static final String DONATION_ID = "6a43fefb-5035-4a9d-83fe-fb5035ea9de7";
+ public static final String DESCRIPTION = "Doação";
+ public static final String ADDRESS_ID = "23dc581a-0900-4a62-9c58-1a09008a62a9";
private Shelter shelter;
private Address address;
@@ -33,20 +36,20 @@ class ShelterTest {
@BeforeEach
void setUp() {
- this.address = new Address("Rua", "377", "Bairro", "Sapucaia", "RS", "93000000");
+ this.address = new Address(ADDRESS_ID, "Rua", "377", "Bairro", "Sapucaia", "RS", "93000000");
this.user = new User(UuidUtils.generateUuid(), "User", "teste@teste.com", UserProfile.BENEFICIARY, "senha");
this.shelter = new Shelter(UUID_TEST, "Abrigo", this.address, this.user);
}
@Test
void shouldCreateShelterWithGivenDetails() {
- Shelter shelter = ShelterFactory.create("Casa 1", this.address, this.user);
+ Shelter shelterTeste = ShelterFactory.create("Casa 1", this.address, this.user);
- assertNotNull(shelter);
- assertTrue(UuidUtils.isValidUUID(shelter.getId()));
- assertEquals("Casa 1", shelter.getShelterName());
- assertEquals(this.address, shelter.getAddress());
- assertEquals(this.user, shelter.getUser());
+ assertNotNull(shelterTeste);
+ assertTrue(UuidUtils.isValidUUID(shelterTeste.getId()));
+ assertEquals("Casa 1", shelterTeste.getShelterName());
+ assertEquals(this.address, shelterTeste.getAddress());
+ assertEquals(this.user, shelterTeste.getUser());
}
@Test
@@ -161,7 +164,7 @@ void shouldChangeShelterName() {
@Test
@SneakyThrows
void shouldChangeAddress() {
- Address newAddress = new Address("Rua", "3924", "Bairro2", "Esteio", "RS", "94000000");
+ Address newAddress = new Address(ADDRESS_ID, "Rua", "3924", "Bairro2", "Esteio", "RS", "94000000");
Field field = Shelter.class.getDeclaredField("address");
field.setAccessible(true);
@@ -185,7 +188,7 @@ void shouldThrowExceptionWhenChangeAddressWithNullAddress() {
@Test
@SneakyThrows
void shouldAddDonation() {
- Donation newDonation = new Donation("Doação", 1);
+ Donation newDonation = new Donation(DONATION_ID, DESCRIPTION, 1);
this.shelter.addDonation(newDonation);
diff --git a/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/AddressTest.java b/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/AddressTest.java
index 17e187c..548ccbf 100644
--- a/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/AddressTest.java
+++ b/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/AddressTest.java
@@ -1,8 +1,11 @@
package diegosneves.github.conectardoacoes.core.domain.shelter.entity.value;
import diegosneves.github.conectardoacoes.core.exception.AddressCreationFailureException;
+import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
@@ -11,22 +14,53 @@
class AddressTest {
+ public static final String ADDRESS_ID = "f3a7d3c9-16a9-41fd-a7d3-c916a981fd2f";
+ public static final String STREET = "Rua";
+ public static final String NUMBER = "123";
+ public static final String NEIGHBORHOOD = "centro";
+ public static final String CITY = "cidade";
+ public static final String STATE = "Estado";
+ public static final String ZIP = "93200100";
+
@Test
void validateAddressFields() {
- Address address = new Address("Rua", "123", "centro", "cidade", "Estado", "93200100");
-
- assertEquals("Rua", address.getStreet());
- assertEquals("123", address.getNumber());
- assertEquals("centro", address.getNeighborhood());
- assertEquals("93200100", address.getZip());
- assertEquals("cidade", address.getCity());
- assertEquals("Estado", address.getState());
+ Address address = new Address(ADDRESS_ID, STREET, NUMBER, NEIGHBORHOOD, CITY, STATE, ZIP);
+
+ assertEquals(ADDRESS_ID, address.getId());
+ assertEquals(STREET, address.getStreet());
+ assertEquals(NUMBER, address.getNumber());
+ assertEquals(NEIGHBORHOOD, address.getNeighborhood());
+ assertEquals(ZIP, address.getZip());
+ assertEquals(CITY, address.getCity());
+ assertEquals(STATE, address.getState());
}
+ @ParameterizedTest
+ @ValueSource(strings = {"", "id"})
+ void shouldThrowExceptionForEmptyOrInvalidAddressId(String value) {
+
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(value, STREET, NUMBER, NEIGHBORHOOD, CITY, STATE, ZIP));
+
+ assertNotNull(exception);
+ assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.INVALID_ID_MESSAGE), exception.getMessage());
+ assertEquals(UuidUtilsException.class, exception.getCause().getClass());
+ }
+
+ @Test
+ void shouldThrowExceptionForNullAddressId() {
+
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(null, STREET, NUMBER, NEIGHBORHOOD, CITY, STATE, ZIP));
+
+ assertNotNull(exception);
+ assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.INVALID_ID_MESSAGE), exception.getMessage());
+ assertEquals(UuidUtilsException.class, exception.getCause().getClass());
+ }
+
+
@Test
void shouldThrowExceptionForEmptyStreetName() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("", "123", "centro", "cidade", "Estado", "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, "", NUMBER, NEIGHBORHOOD, CITY, STATE, ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.STREET_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -35,7 +69,7 @@ void shouldThrowExceptionForEmptyStreetName() {
@Test
void shouldThrowExceptionForNullStreetName() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(null, "123", "centro", "cidade", "Estado", "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID,null, NUMBER, NEIGHBORHOOD, CITY, STATE, ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.STREET_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -44,7 +78,7 @@ void shouldThrowExceptionForNullStreetName() {
@Test
void shouldThrowExceptionForEmptyNumber() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("Rua", " ", "centro", "cidade", "Estado", "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, STREET, " ", NEIGHBORHOOD, CITY, STATE, ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.RESIDENCE_NUMBER_ERROR_MESSAGE), exception.getMessage());
@@ -53,7 +87,7 @@ void shouldThrowExceptionForEmptyNumber() {
@Test
void shouldThrowExceptionForNullNumber() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("null", null, "centro", "cidade", "Estado", "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, "null", null, NEIGHBORHOOD, CITY, STATE, ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.RESIDENCE_NUMBER_ERROR_MESSAGE), exception.getMessage());
@@ -62,7 +96,7 @@ void shouldThrowExceptionForNullNumber() {
@Test
void shouldThrowExceptionForEmptyNeighborhoodName() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("Rua", "123", "", "cidade", "Estado", "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, STREET, NUMBER, "", CITY, STATE, ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.NEIGHBORHOOD_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -71,7 +105,7 @@ void shouldThrowExceptionForEmptyNeighborhoodName() {
@Test
void shouldThrowExceptionForNullNeighborhoodName() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("null", "123", null, "cidade", "Estado", "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, "null", NUMBER, null, CITY, STATE, ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.NEIGHBORHOOD_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -80,7 +114,7 @@ void shouldThrowExceptionForNullNeighborhoodName() {
@Test
void shouldThrowExceptionForEmptyCityName() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("rua", "123", "centro", " ", "Estado", "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, "rua", NUMBER, NEIGHBORHOOD, " ", STATE, ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.CITY_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -89,7 +123,7 @@ void shouldThrowExceptionForEmptyCityName() {
@Test
void shouldThrowExceptionForNullCityName() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("null", "123", "centro", null, "Estado", "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, "null", NUMBER, NEIGHBORHOOD, null, STATE, ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.CITY_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -98,7 +132,7 @@ void shouldThrowExceptionForNullCityName() {
@Test
void shouldThrowExceptionForEmptyStateName() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("rua", "123", "centro", "cidade", " ", "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, "rua", NUMBER, NEIGHBORHOOD, CITY, " ", ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.STATE_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -107,7 +141,7 @@ void shouldThrowExceptionForEmptyStateName() {
@Test
void shouldThrowExceptionForNullStateName() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("null", "123", "centro", "cidade", null, "93200100"));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, "null", NUMBER, NEIGHBORHOOD, CITY, null, ZIP));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.STATE_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -116,7 +150,7 @@ void shouldThrowExceptionForNullStateName() {
@Test
void shouldThrowExceptionForEmptyZipCode() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("rua", "123", "centro", "cidade", "Estado", ""));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, "rua", NUMBER, NEIGHBORHOOD, CITY, STATE, ""));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.CEP_ERROR_MESSAGE), exception.getMessage());
@@ -125,7 +159,7 @@ void shouldThrowExceptionForEmptyZipCode() {
@Test
void shouldThrowExceptionForNullZipCode() {
- AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address("null", "123", "centro", "cidade", "Estado", null));
+ AddressCreationFailureException exception = assertThrows(AddressCreationFailureException.class, () -> new Address(ADDRESS_ID, "null", NUMBER, NEIGHBORHOOD, CITY, STATE, null));
assertNotNull(exception);
assertEquals(AddressCreationFailureException.ERROR.buildMessage(Address.CEP_ERROR_MESSAGE), exception.getMessage());
diff --git a/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/DonationTest.java b/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/DonationTest.java
index 1bd570d..41ae4c1 100644
--- a/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/DonationTest.java
+++ b/src/test/java/diegosneves/github/conectardoacoes/core/domain/shelter/entity/value/DonationTest.java
@@ -2,8 +2,11 @@
import diegosneves.github.conectardoacoes.core.enums.ExceptionDetails;
import diegosneves.github.conectardoacoes.core.exception.DonationRegisterFailureException;
+import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.junit.jupiter.MockitoExtension;
import static org.junit.jupiter.api.Assertions.*;
@@ -11,44 +14,66 @@
@ExtendWith(MockitoExtension.class)
class DonationTest {
+ public static final String DONATION_ID = "5945ced6-9f60-4c75-85ce-d69f60fc75c4";
+ public static final String DONATION_DESCRIPTION = "Item 01";
+ public static final int DONATION_AMOUNT = 2;
+
@Test
void donationObjectShouldBeInitializedWithCorrectValues() {
- Donation donation = new Donation("Item 01", 2);
+ Donation donation = new Donation(DONATION_ID, DONATION_DESCRIPTION, DONATION_AMOUNT);
assertNotNull(donation);
- assertEquals("Item 01", donation.getDescription());
- assertEquals(2, donation.getAmount());
+ assertEquals(DONATION_ID, donation.getId());
+ assertEquals(DONATION_DESCRIPTION, donation.getDescription());
+ assertEquals(DONATION_AMOUNT, donation.getAmount());
}
@Test
void donationObjectShouldBeInitializedWithDefaultAmountWhenGivenAmountIsZero() {
- Donation donation = new Donation("Item 02", 0);
+ Donation donation = new Donation(DONATION_ID, DONATION_DESCRIPTION, 0);
assertNotNull(donation);
- assertEquals("Item 02", donation.getDescription());
+ assertEquals(DONATION_ID, donation.getId());
+ assertEquals(DONATION_DESCRIPTION, donation.getDescription());
assertEquals(Donation.DEFAULT_DONATION_AMOUNT, donation.getAmount());
}
@Test
void shouldNotBeInitializedWithNullDescription() {
- DonationRegisterFailureException exception = assertThrows(DonationRegisterFailureException.class, () -> new Donation(null, 1));
+ DonationRegisterFailureException exception = assertThrows(DonationRegisterFailureException.class, () -> new Donation(DONATION_ID,null, 1));
assertNotNull(exception);
assertEquals(ExceptionDetails.DONATION_CREATION_ERROR.buildMessage(Donation.INVALID_DESCRIPTION_ERROR), exception.getMessage());
}
@Test
void shouldNotBeInitializedWithEmptyDescription() {
- DonationRegisterFailureException exception = assertThrows(DonationRegisterFailureException.class, () -> new Donation(" ", 1));
+ DonationRegisterFailureException exception = assertThrows(DonationRegisterFailureException.class, () -> new Donation(DONATION_ID," ", -1));
assertNotNull(exception);
assertEquals(ExceptionDetails.DONATION_CREATION_ERROR.buildMessage(Donation.INVALID_DESCRIPTION_ERROR), exception.getMessage());
}
@Test
void shouldNotBeInitializedWithNullAmount() {
- DonationRegisterFailureException exception = assertThrows(DonationRegisterFailureException.class, () -> new Donation("null", null));
+ DonationRegisterFailureException exception = assertThrows(DonationRegisterFailureException.class, () -> new Donation(DONATION_ID,"null", null));
assertNotNull(exception);
assertEquals(ExceptionDetails.DONATION_CREATION_ERROR.buildMessage(Donation.INVALID_QUANTITY), exception.getMessage());
}
+ @Test
+ void shouldNotBeInitializedWithNullId() {
+ DonationRegisterFailureException exception = assertThrows(DonationRegisterFailureException.class, () -> new Donation(null, DONATION_DESCRIPTION, DONATION_AMOUNT));
+ assertNotNull(exception);
+ assertEquals(ExceptionDetails.DONATION_CREATION_ERROR.buildMessage(Donation.INVALID_ID_MESSAGE), exception.getMessage());
+ assertEquals(UuidUtilsException.class, exception.getCause().getClass());
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {" ", "null"})
+ void shouldNotBeInitializedWithEmptyOrInvalidId(String id) {
+ DonationRegisterFailureException exception = assertThrows(DonationRegisterFailureException.class, () -> new Donation(id, DONATION_DESCRIPTION, DONATION_AMOUNT));
+ assertNotNull(exception);
+ assertEquals(ExceptionDetails.DONATION_CREATION_ERROR.buildMessage(Donation.INVALID_ID_MESSAGE), exception.getMessage());
+ assertEquals(UuidUtilsException.class, exception.getCause().getClass());
+ }
}
diff --git a/src/test/java/diegosneves/github/conectardoacoes/core/service/ShelterServiceTest.java b/src/test/java/diegosneves/github/conectardoacoes/core/service/ShelterServiceTest.java
index 4e2da2e..0709079 100644
--- a/src/test/java/diegosneves/github/conectardoacoes/core/service/ShelterServiceTest.java
+++ b/src/test/java/diegosneves/github/conectardoacoes/core/service/ShelterServiceTest.java
@@ -4,7 +4,7 @@
import diegosneves.github.conectardoacoes.core.domain.shelter.entity.ShelterContract;
import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Address;
import diegosneves.github.conectardoacoes.core.domain.shelter.entity.value.Donation;
-import diegosneves.github.conectardoacoes.core.domain.shelter.shared.repository.ShelterRepository;
+import diegosneves.github.conectardoacoes.core.domain.shelter.shared.repository.ShelterContractRepository;
import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;
@@ -14,16 +14,23 @@
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.test.context.junit.jupiter.SpringExtension;
-import java.lang.reflect.Field;
import java.util.List;
-import static org.junit.jupiter.api.Assertions.*;
+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;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.never;
@@ -35,11 +42,14 @@
class ShelterServiceTest {
public static final String SHELTER_IDENTIFIER = "89142bda-7b0c-4421-af28-f9cadb316024";
+ public static final String SHELTER_NAME = "Abrigo";
+
public static final String USER_UUID = "0ed6e6a1-882c-4d2d-83ee-67034ee1ab9f";
public static final String USERNAME = "Fulano";
public static final String USER_EMAIL = "teste@email.com";
public static final String USER_PASSWORD = "senha";
- public static final String SHELTER_NAME = "Abrigo";
+
+ public static final String ADDRESS_ID = "b6912f61-312b-48c2-912f-61312b38c249";
public static final String ADDRESS_STREET = "Rua";
public static final String BUILDING_NUMBER = "54";
public static final String NEIGHBORHOOD = "Bairro";
@@ -47,11 +57,15 @@ class ShelterServiceTest {
public static final String STATE_ABBREVIATION = "RS";
public static final String SHELTER_ZIPCODE = "95000000";
+ public static final String DONATION_ID = "8df29915-a43d-4dc2-b299-15a43d9dc2b2";
+ public static final String DONATED_ITEM = "item";
+ public static final int AMOUNT = 1;
+
@InjectMocks
private ShelterService service;
@Mock
- private ShelterRepository repository;
+ private ShelterContractRepository repository;
@Captor
private ArgumentCaptor shelterCaptor;
@@ -63,17 +77,17 @@ class ShelterServiceTest {
@BeforeEach
void setUp() {
this.user = new User(USER_UUID, USERNAME, USER_EMAIL, UserProfile.BENEFICIARY, USER_PASSWORD);
- this.address = new Address(ADDRESS_STREET, BUILDING_NUMBER, NEIGHBORHOOD, SHELTER_CITY, STATE_ABBREVIATION, SHELTER_ZIPCODE);
+ this.address = new Address(ADDRESS_ID, ADDRESS_STREET, BUILDING_NUMBER, NEIGHBORHOOD, SHELTER_CITY, STATE_ABBREVIATION, SHELTER_ZIPCODE);
this.shelter = new Shelter(SHELTER_IDENTIFIER, SHELTER_NAME, this.address, this.user);
}
@Test
void shouldReturnShelterContract() {
- when(this.repository.save(any(ShelterContract.class))).thenReturn(this.shelter);
+ when(this.repository.persist(any(ShelterContract.class))).thenReturn(this.shelter);
ShelterContract actual = this.service.createShelter(SHELTER_NAME, this.address, this.user);
- verify(this.repository, times(1)).save(this.shelterCaptor.capture());
+ verify(this.repository, times(AMOUNT)).persist(this.shelterCaptor.capture());
assertNotNull(actual);
assertNotNull(this.shelterCaptor.getValue());
@@ -91,7 +105,7 @@ void shouldThrowShelterCreationFailureExceptionWhenShelterNameIsNull() {
Exception actual = assertThrows(Exception.class,
() -> this.service.createShelter(null, this.address, this.user));
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(actual);
assertEquals(ShelterCreationFailureException.class, actual.getClass());
@@ -103,7 +117,7 @@ void shouldThrowShelterCreationFailureExceptionWhenShelterNameIsEmpty() {
Exception actual = assertThrows(Exception.class,
() -> this.service.createShelter("", this.address, this.user));
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(actual);
assertEquals(ShelterCreationFailureException.class, actual.getClass());
@@ -115,7 +129,7 @@ void shouldThrowShelterCreationFailureExceptionWhenShelterAddressIsNull() {
Exception actual = assertThrows(Exception.class,
() -> this.service.createShelter(SHELTER_NAME, null, this.user));
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(actual);
assertEquals(ShelterCreationFailureException.class, actual.getClass());
@@ -127,7 +141,7 @@ void shouldThrowShelterCreationFailureExceptionWhenShelterUserIsNull() {
Exception actual = assertThrows(Exception.class,
() -> this.service.createShelter(SHELTER_NAME, this.address, null));
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(actual);
assertEquals(ShelterCreationFailureException.class, actual.getClass());
@@ -135,11 +149,11 @@ void shouldThrowShelterCreationFailureExceptionWhenShelterUserIsNull() {
@Test
void shouldRetrieveShelterContractUsingGivenShelterIdentifier() {
- when(this.repository.findById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
+ when(this.repository.findEntityById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
ShelterContract actual = this.service.getShelter(SHELTER_IDENTIFIER);
- verify(this.repository, times(1)).findById(SHELTER_IDENTIFIER);
+ verify(this.repository, times(AMOUNT)).findEntityById(SHELTER_IDENTIFIER);
assertNotNull(actual);
assertEquals(this.shelter, actual);
@@ -147,11 +161,11 @@ void shouldRetrieveShelterContractUsingGivenShelterIdentifier() {
@Test
void shouldRetrieveNullShelterContractUsingGivenShelterIdentifier() {
- when(this.repository.findById(SHELTER_IDENTIFIER)).thenReturn(null);
+ when(this.repository.findEntityById(SHELTER_IDENTIFIER)).thenReturn(null);
ShelterContract actual = this.service.getShelter(SHELTER_IDENTIFIER);
- verify(this.repository, times(1)).findById(SHELTER_IDENTIFIER);
+ verify(this.repository, times(AMOUNT)).findEntityById(SHELTER_IDENTIFIER);
assertNull(actual);
}
@@ -161,7 +175,7 @@ void shouldThrowExceptionWhenGivenNullShelterId() {
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.getShelter(null));
- verify(this.repository, never()).findById(anyString());
+ verify(this.repository, never()).findEntityById(anyString());
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -172,7 +186,7 @@ void shouldThrowExceptionWhenGivenEmptyShelterId() {
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.getShelter(""));
- verify(this.repository, never()).findById(anyString());
+ verify(this.repository, never()).findEntityById(anyString());
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -183,7 +197,7 @@ void shouldThrowExceptionWhenGivenInvalidShelterId() {
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.getShelter("idInvalid"));
- verify(this.repository, never()).findById(anyString());
+ verify(this.repository, never()).findEntityById(anyString());
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -193,12 +207,12 @@ void shouldThrowExceptionWhenGivenInvalidShelterId() {
@Test
void shouldChangeShelterNameWhenGivenValidShelterIdentifier() {
String newShelterName = "newShelterName";
- when(this.repository.findById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
+ when(this.repository.findEntityById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
this.service.changeShelterName(SHELTER_IDENTIFIER, newShelterName);
- verify(this.repository, times(1)).findById(SHELTER_IDENTIFIER);
- verify(this.repository, times(1)).save(this.shelterCaptor.capture());
+ verify(this.repository, times(AMOUNT)).findEntityById(SHELTER_IDENTIFIER);
+ verify(this.repository, times(AMOUNT)).persist(this.shelterCaptor.capture());
assertNotNull(shelterCaptor.getValue());
Shelter updatedShelter = this.shelterCaptor.getValue();
@@ -215,8 +229,8 @@ void shouldThrowShelterServiceFailureExceptionWhenShelterNameIsEmpty() {
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.changeShelterName(SHELTER_IDENTIFIER, newShelterName));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -228,8 +242,8 @@ void shouldThrowShelterServiceFailureExceptionWhenShelterNameIsNull() {
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.changeShelterName(SHELTER_IDENTIFIER, null));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_NAME_ERROR_MESSAGE), exception.getMessage());
@@ -241,8 +255,8 @@ void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsInvalidOnChangeShel
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.changeShelterName("SHELTER_IDENTIFIER", SHELTER_NAME));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -251,13 +265,13 @@ void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsInvalidOnChangeShel
@Test
void shouldUpdateAndSaveShelterAddressGivenValidShelterId() {
- Address addressUpdate = new Address(ADDRESS_STREET, "377", NEIGHBORHOOD, "Esteio", STATE_ABBREVIATION, SHELTER_ZIPCODE);
- when(this.repository.findById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
+ Address addressUpdate = new Address(ADDRESS_ID, ADDRESS_STREET, "377", NEIGHBORHOOD, "Esteio", STATE_ABBREVIATION, SHELTER_ZIPCODE);
+ when(this.repository.findEntityById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
this.service.changeAddress(SHELTER_IDENTIFIER, addressUpdate);
- verify(this.repository, times(1)).findById(SHELTER_IDENTIFIER);
- verify(this.repository, times(1)).save(this.shelterCaptor.capture());
+ verify(this.repository, times(AMOUNT)).findEntityById(SHELTER_IDENTIFIER);
+ verify(this.repository, times(AMOUNT)).persist(this.shelterCaptor.capture());
assertNotNull(shelterCaptor.getValue());
Shelter updatedShelter = this.shelterCaptor.getValue();
@@ -270,13 +284,13 @@ void shouldUpdateAndSaveShelterAddressGivenValidShelterId() {
@Test
void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsEmptyOnChangeAddress() {
- Address addressUpdate = new Address(ADDRESS_STREET, "377", NEIGHBORHOOD, "Esteio", STATE_ABBREVIATION, SHELTER_ZIPCODE);
+ Address addressUpdate = new Address(ADDRESS_ID, ADDRESS_STREET, "377", NEIGHBORHOOD, "Esteio", STATE_ABBREVIATION, SHELTER_ZIPCODE);
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.changeAddress("", addressUpdate));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -284,13 +298,13 @@ void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsEmptyOnChangeAddres
@Test
void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsNullOnChangeAddress() {
- Address addressUpdate = new Address(ADDRESS_STREET, "377", NEIGHBORHOOD, "Esteio", STATE_ABBREVIATION, SHELTER_ZIPCODE);
+ Address addressUpdate = new Address(ADDRESS_ID, ADDRESS_STREET, "377", NEIGHBORHOOD, "Esteio", STATE_ABBREVIATION, SHELTER_ZIPCODE);
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.changeAddress(null, addressUpdate));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -298,13 +312,13 @@ void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsNullOnChangeAddress
@Test
void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsInvalidOnChangeAddress() {
- Address addressUpdate = new Address(ADDRESS_STREET, "377", NEIGHBORHOOD, "Esteio", STATE_ABBREVIATION, SHELTER_ZIPCODE);
+ Address addressUpdate = new Address(ADDRESS_ID, ADDRESS_STREET, "377", NEIGHBORHOOD, "Esteio", STATE_ABBREVIATION, SHELTER_ZIPCODE);
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.changeAddress("SHELTER_IDENTIFIER", addressUpdate));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -317,8 +331,8 @@ void shouldThrowShelterServiceFailureExceptionWhenNewAddressIsNullOnChangeAddres
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.changeAddress(SHELTER_IDENTIFIER, null));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.ERROR_MESSAGE_ADDRESS_NULL), exception.getMessage());
@@ -326,31 +340,31 @@ void shouldThrowShelterServiceFailureExceptionWhenNewAddressIsNullOnChangeAddres
@Test
void shouldAddDonationToShelter() {
- Donation donation = new Donation("item", 1);
+ Donation donation = new Donation(DONATION_ID, DONATED_ITEM, AMOUNT);
- when(this.repository.findById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
+ when(this.repository.findEntityById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
this.service.addDonation(SHELTER_IDENTIFIER, donation);
- verify(this.repository, times(1)).findById(SHELTER_IDENTIFIER);
- verify(this.repository, times(1)).save(this.shelterCaptor.capture());
+ verify(this.repository, times(1)).findEntityById(SHELTER_IDENTIFIER);
+ verify(this.repository, times(1)).persist(this.shelterCaptor.capture());
assertNotNull(shelterCaptor.getValue());
Shelter updatedShelter = this.shelterCaptor.getValue();
assertFalse(updatedShelter.getDonations().isEmpty());
- assertEquals(1, updatedShelter.getDonations().size());
+ assertEquals(AMOUNT, updatedShelter.getDonations().size());
assertEquals(donation, updatedShelter.getDonations().get(0));
}
@Test
void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsNullOnAddDonation() {
- Donation donation = new Donation("item", 1);
+ Donation donation = new Donation(DONATION_ID, DONATED_ITEM, AMOUNT);
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.addDonation(null, donation));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -358,13 +372,13 @@ void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsNullOnAddDonation()
@Test
void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsEmptyOnAddDonation() {
- Donation donation = new Donation("item", 1);
+ Donation donation = new Donation(DONATION_ID, DONATED_ITEM, AMOUNT);
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.addDonation(" ", donation));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -372,13 +386,13 @@ void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsEmptyOnAddDonation(
@Test
void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsInvalidOnAddDonation() {
- Donation donation = new Donation("item", 1);
+ Donation donation = new Donation(DONATION_ID, DONATED_ITEM, AMOUNT);
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.addDonation("SHELTER_IDENTIFIER", donation));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
@@ -391,8 +405,8 @@ void shouldThrowShelterServiceFailureExceptionWhenDonationIsNullOnAddDonation()
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class,
() -> this.service.addDonation(SHELTER_IDENTIFIER, null));
- verify(this.repository, never()).findById(anyString());
- verify(this.repository, never()).save(any(ShelterContract.class));
+ verify(this.repository, never()).findEntityById(anyString());
+ verify(this.repository, never()).persist(any(ShelterContract.class));
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.DONATION_REQUIRED_ERROR_MESSAGE), exception.getMessage());
@@ -400,27 +414,27 @@ void shouldThrowShelterServiceFailureExceptionWhenDonationIsNullOnAddDonation()
@Test
void shouldReturnListOfDonations() {
- Donation donation = new Donation("item", 1);
+ Donation donation = new Donation(DONATION_ID, DONATED_ITEM, AMOUNT);
this.shelter.addDonation(donation);
- when(this.repository.findById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
+ when(this.repository.findEntityById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
List list = this.service.getDonations(SHELTER_IDENTIFIER);
- verify(this.repository, times(1)).findById(SHELTER_IDENTIFIER);
+ verify(this.repository, times(1)).findEntityById(SHELTER_IDENTIFIER);
assertNotNull(list);
assertFalse(this.shelter.getDonations().isEmpty());
- assertEquals(1, list.size());
+ assertEquals(AMOUNT, list.size());
assertEquals(donation, list.get(0));
}
@Test
void shouldReturnListOfDonationsEmpty() {
- when(this.repository.findById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
+ when(this.repository.findEntityById(SHELTER_IDENTIFIER)).thenReturn(this.shelter);
List list = this.service.getDonations(SHELTER_IDENTIFIER);
- verify(this.repository, times(1)).findById(SHELTER_IDENTIFIER);
+ verify(this.repository, times(1)).findEntityById(SHELTER_IDENTIFIER);
assertNotNull(list);
assertTrue(this.shelter.getDonations().isEmpty());
@@ -431,29 +445,19 @@ void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsNullOnGetDonations(
ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class, () -> this.service.getDonations(null));
- verify(this.repository, never()).findById(anyString());
-
- assertNotNull(exception);
- assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
- }
-
- @Test
- void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsEmptyOnGetDonations() {
-
- ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class, () -> this.service.getDonations(""));
-
- verify(this.repository, never()).findById(anyString());
+ verify(this.repository, never()).findEntityById(anyString());
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
}
- @Test
- void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsInvalidOnGetDonations() {
+ @ParameterizedTest
+ @ValueSource(strings = {"", "SHELTER_IDENTIFIER"})
+ void shouldThrowShelterServiceFailureExceptionWhenShelterIdIsEmptyOrInvalidOnGetDonations(String shelterIdentifier) {
- ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class, () -> this.service.getDonations("SHELTER_IDENTIFIER"));
+ ShelterServiceFailureException exception = assertThrows(ShelterServiceFailureException.class, () -> this.service.getDonations(shelterIdentifier));
- verify(this.repository, never()).findById(anyString());
+ verify(this.repository, never()).findEntityById(anyString());
assertNotNull(exception);
assertEquals(ShelterServiceFailureException.ERROR.buildMessage(ShelterService.INVALID_SHELTER_ID_MESSAGE), exception.getMessage());
diff --git a/src/test/java/diegosneves/github/conectardoacoes/core/service/UserServiceTest.java b/src/test/java/diegosneves/github/conectardoacoes/core/service/UserServiceTest.java
index 9c9054b..3341449 100644
--- a/src/test/java/diegosneves/github/conectardoacoes/core/service/UserServiceTest.java
+++ b/src/test/java/diegosneves/github/conectardoacoes/core/service/UserServiceTest.java
@@ -1,12 +1,9 @@
package diegosneves.github.conectardoacoes.core.service;
-import diegosneves.github.conectardoacoes.core.domain.shelter.entity.ShelterContract;
import diegosneves.github.conectardoacoes.core.domain.user.entity.User;
import diegosneves.github.conectardoacoes.core.domain.user.entity.UserContract;
import diegosneves.github.conectardoacoes.core.domain.user.entity.value.UserProfile;
-import diegosneves.github.conectardoacoes.core.domain.user.shared.repository.UserRepository;
-import diegosneves.github.conectardoacoes.core.enums.ExceptionDetails;
-import diegosneves.github.conectardoacoes.core.exception.ShelterCreationFailureException;
+import diegosneves.github.conectardoacoes.core.domain.user.shared.repository.UserContractRepository;
import diegosneves.github.conectardoacoes.core.exception.UserCreationFailureException;
import diegosneves.github.conectardoacoes.core.exception.UserServiceFailureException;
import diegosneves.github.conectardoacoes.core.exception.UuidUtilsException;
@@ -19,7 +16,6 @@
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -46,7 +42,7 @@ class UserServiceTest {
private UserService userService;
@Mock
- private UserRepository userRepository;
+ private UserContractRepository userContractRepository;
@Captor
private ArgumentCaptor userCaptor;
@@ -60,11 +56,11 @@ void setUp() {
@Test
void shouldCreateUserAndReturnCreatedUser() {
- when(this.userRepository.save(any(UserContract.class))).thenReturn(this.user);
+ when(this.userContractRepository.persist(any(UserContract.class))).thenReturn(this.user);
UserContract actual = this.userService.createUser(USERNAME, USER_EMAIL, UserProfile.BENEFICIARY, USER_PASSWORD);
- verify(this.userRepository, times(1)).save(this.userCaptor.capture());
+ verify(this.userContractRepository, times(1)).persist(this.userCaptor.capture());
assertNotNull(this.userCaptor.getValue());
User returnedUser = this.userCaptor.getValue();
@@ -87,7 +83,7 @@ void shouldThrowUserCreationFailureExceptionWhenUsernameIsNull() {
Exception actual = assertThrows(Exception.class,
() -> this.userService.createUser(null, USER_EMAIL, UserProfile.BENEFICIARY, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.class, actual.getClass());
@@ -99,7 +95,7 @@ void shouldThrowUserCreationFailureExceptionWhenUsernameIsEmpty() {
Exception actual = assertThrows(Exception.class,
() -> this.userService.createUser(" ", USER_EMAIL, UserProfile.BENEFICIARY, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.class, actual.getClass());
@@ -111,7 +107,7 @@ void shouldThrowUserCreationFailureExceptionWhenUserEmailIsNull() {
Exception actual = assertThrows(Exception.class,
() -> this.userService.createUser(USERNAME, null, UserProfile.BENEFICIARY, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.class, actual.getClass());
@@ -123,7 +119,7 @@ void shouldThrowUserCreationFailureExceptionWhenUserEmailIsEmpty() {
Exception actual = assertThrows(Exception.class,
() -> this.userService.createUser(USERNAME, "", UserProfile.BENEFICIARY, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.class, actual.getClass());
@@ -135,7 +131,7 @@ void shouldThrowUserCreationFailureExceptionWhenUserProfileIsNull() {
Exception actual = assertThrows(Exception.class,
() -> this.userService.createUser(USERNAME, USER_EMAIL, null, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.class, actual.getClass());
@@ -147,7 +143,7 @@ void shouldThrowUserCreationFailureExceptionWhenUserPasswordIsNull() {
Exception actual = assertThrows(Exception.class,
() -> this.userService.createUser(USERNAME, USER_EMAIL, UserProfile.BENEFICIARY, null));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.class, actual.getClass());
@@ -159,7 +155,7 @@ void shouldThrowUserCreationFailureExceptionWhenUserPasswordIsEmpty() {
Exception actual = assertThrows(Exception.class,
() -> this.userService.createUser(USERNAME, USER_EMAIL, UserProfile.BENEFICIARY, " "));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.class, actual.getClass());
@@ -171,7 +167,7 @@ void shouldThrowExceptionWhenUsernameIsNullOnCreateUser() {
UserCreationFailureException actual = assertThrows(UserCreationFailureException.class,
() -> this.userService.createUser(null, USER_EMAIL, UserProfile.BENEFICIARY, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.ERROR.buildMessage(String.format(User.USERNAME_REQUIRED, UserProfile.BENEFICIARY)), actual.getMessage());
@@ -183,7 +179,7 @@ void shouldThrowExceptionWhenUsernameIsEmptyOnCreateUser() {
UserCreationFailureException actual = assertThrows(UserCreationFailureException.class,
() -> this.userService.createUser(" ", USER_EMAIL, UserProfile.BENEFICIARY, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.ERROR.buildMessage(String.format(User.USERNAME_REQUIRED, UserProfile.BENEFICIARY)), actual.getMessage());
@@ -195,7 +191,7 @@ void shouldThrowExceptionWhenEmailIsNullOnCreateUser() {
UserCreationFailureException actual = assertThrows(UserCreationFailureException.class,
() -> this.userService.createUser(USERNAME, null, UserProfile.BENEFICIARY, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.ERROR.buildMessage(User.EMAIL_NOT_PROVIDED), actual.getMessage());
@@ -207,7 +203,7 @@ void shouldThrowExceptionWhenEmailIsEmptyOnCreateUser() {
UserCreationFailureException actual = assertThrows(UserCreationFailureException.class,
() -> this.userService.createUser(USERNAME, "", UserProfile.BENEFICIARY, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.ERROR.buildMessage(User.EMAIL_NOT_PROVIDED), actual.getMessage());
@@ -219,7 +215,7 @@ void shouldThrowExceptionWhenUserProfileIsNullOnCreateUser() {
UserCreationFailureException actual = assertThrows(UserCreationFailureException.class,
() -> this.userService.createUser(USERNAME, USER_EMAIL, null, USER_PASSWORD));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.ERROR.buildMessage(User.PROFILE_NOT_PROVIDED), actual.getMessage());
@@ -231,7 +227,7 @@ void shouldThrowExceptionWhenPasswordIsNullOnCreateUser() {
UserCreationFailureException actual = assertThrows(UserCreationFailureException.class,
() -> this.userService.createUser(USERNAME, USER_EMAIL, UserProfile.BENEFICIARY, null));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.ERROR.buildMessage(User.PASSWORD_NOT_PROVIDED), actual.getMessage());
@@ -243,7 +239,7 @@ void shouldThrowExceptionWhenPasswordIsEmptyOnCreateUser() {
UserCreationFailureException actual = assertThrows(UserCreationFailureException.class,
() -> this.userService.createUser(USERNAME, USER_EMAIL, UserProfile.BENEFICIARY, " "));
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(actual);
assertEquals(UserCreationFailureException.ERROR.buildMessage(User.PASSWORD_NOT_PROVIDED), actual.getMessage());
@@ -251,11 +247,11 @@ void shouldThrowExceptionWhenPasswordIsEmptyOnCreateUser() {
@Test
void shouldGetUserById() {
- when(this.userRepository.findById(USER_UUID)).thenReturn(this.user);
+ when(this.userContractRepository.findEntityById(USER_UUID)).thenReturn(this.user);
UserContract actual = this.userService.getUser(USER_UUID);
- verify(this.userRepository, times(1)).findById(USER_UUID);
+ verify(this.userContractRepository, times(1)).findEntityById(USER_UUID);
assertNotNull(actual);
assertEquals(this.user, actual);
@@ -263,11 +259,11 @@ void shouldGetUserById() {
@Test
void shouldReturnNullWhenUserNotFoundOnGetUser() {
- when(this.userRepository.findById(USER_IDENTIFIER)).thenReturn(null);
+ when(this.userContractRepository.findEntityById(USER_IDENTIFIER)).thenReturn(null);
UserContract actual = this.userService.getUser(USER_IDENTIFIER);
- verify(this.userRepository, times(1)).findById(USER_IDENTIFIER);
+ verify(this.userContractRepository, times(1)).findEntityById(USER_IDENTIFIER);
assertNull(actual);
}
@@ -277,7 +273,7 @@ void shouldThrowUserServiceFailureExceptionWhenNullUserIdProvidedOnGetUser() {
UserServiceFailureException actual = assertThrows(UserServiceFailureException.class, () -> this.userService.getUser(null));
- verify(this.userRepository, never()).findById(anyString());
+ verify(this.userContractRepository, never()).findEntityById(anyString());
assertNotNull(actual);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_IDENTIFIER_ERROR_MESSAGE), actual.getMessage());
@@ -288,7 +284,7 @@ void shouldThrowUserServiceFailureExceptionWhenEmptyUserIdProvidedOnGetUser() {
UserServiceFailureException actual = assertThrows(UserServiceFailureException.class, () -> this.userService.getUser(" "));
- verify(this.userRepository, never()).findById(anyString());
+ verify(this.userContractRepository, never()).findEntityById(anyString());
assertNotNull(actual);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_IDENTIFIER_ERROR_MESSAGE), actual.getMessage());
@@ -299,7 +295,7 @@ void shouldThrowUserServiceFailureExceptionWhenInvalidUserIdProvidedOnGetUser()
UserServiceFailureException actual = assertThrows(UserServiceFailureException.class, () -> this.userService.getUser("id"));
- verify(this.userRepository, never()).findById(anyString());
+ verify(this.userContractRepository, never()).findEntityById(anyString());
assertNotNull(actual);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_IDENTIFIER_ERROR_MESSAGE), actual.getMessage());
@@ -309,12 +305,12 @@ void shouldThrowUserServiceFailureExceptionWhenInvalidUserIdProvidedOnGetUser()
@Test
void shouldChangeUserPasswordAndPersistTheChange() {
String newPassword = "newPassword";
- when(this.userRepository.findById(USER_UUID)).thenReturn(this.user);
+ when(this.userContractRepository.findEntityById(USER_UUID)).thenReturn(this.user);
this.userService.changePassword(USER_UUID, newPassword);
- verify(this.userRepository, times(1)).findById(USER_UUID);
- verify(this.userRepository, times(1)).save(this.userCaptor.capture());
+ verify(this.userContractRepository, times(1)).findEntityById(USER_UUID);
+ verify(this.userContractRepository, times(1)).persist(this.userCaptor.capture());
assertNotNull(userCaptor.getValue());
User updatedUser = userCaptor.getValue();
@@ -331,8 +327,8 @@ void shouldThrowUserServiceFailureExceptionWhenNewPasswordIsNull() {
UserServiceFailureException exception = assertThrows(UserServiceFailureException.class,
() -> this.userService.changePassword(USER_UUID, null));
- verify(this.userRepository, never()).findById(USER_UUID);
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).findEntityById(USER_UUID);
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(exception);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_NEW_PASSWORD_MESSAGE), exception.getMessage());
@@ -345,8 +341,8 @@ void shouldThrowUserServiceFailureExceptionWhenNewPasswordIsEmpty() {
UserServiceFailureException exception = assertThrows(UserServiceFailureException.class,
() -> this.userService.changePassword(USER_UUID, newPassword));
- verify(this.userRepository, never()).findById(USER_UUID);
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).findEntityById(USER_UUID);
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(exception);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_NEW_PASSWORD_MESSAGE), exception.getMessage());
@@ -355,13 +351,13 @@ void shouldThrowUserServiceFailureExceptionWhenNewPasswordIsEmpty() {
@Test
void shouldThrowUserServiceFailureExceptionWhenUserNotFound() {
String newPassword = "newPassword";
- when(this.userRepository.findById(USER_UUID)).thenReturn(null);
+ when(this.userContractRepository.findEntityById(USER_UUID)).thenReturn(null);
UserServiceFailureException exception = assertThrows(UserServiceFailureException.class,
() -> this.userService.changePassword(USER_UUID, newPassword));
- verify(this.userRepository, times(1)).findById(USER_UUID);
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, times(1)).findEntityById(USER_UUID);
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(exception);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.USER_NOT_FOUND_MESSAGE), exception.getMessage());
@@ -372,7 +368,7 @@ void shouldThrowUserServiceFailureExceptionWhenNullUserIdProvidedOnChangePasswor
UserServiceFailureException actual = assertThrows(UserServiceFailureException.class, () -> this.userService.changePassword(null, "newPassword"));
- verify(this.userRepository, never()).findById(anyString());
+ verify(this.userContractRepository, never()).findEntityById(anyString());
assertNotNull(actual);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_IDENTIFIER_ERROR_MESSAGE), actual.getMessage());
@@ -383,7 +379,7 @@ void shouldThrowUserServiceFailureExceptionWhenEmptyUserIdProvidedOnChangePasswo
UserServiceFailureException actual = assertThrows(UserServiceFailureException.class, () -> this.userService.changePassword(" ", "newPassword"));
- verify(this.userRepository, never()).findById(anyString());
+ verify(this.userContractRepository, never()).findEntityById(anyString());
assertNotNull(actual);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_IDENTIFIER_ERROR_MESSAGE), actual.getMessage());
@@ -394,7 +390,7 @@ void shouldThrowUserServiceFailureExceptionWhenInvalidUserIdProvidedOnChangePass
UserServiceFailureException actual = assertThrows(UserServiceFailureException.class, () -> this.userService.changePassword("Invalid", "newPassword"));
- verify(this.userRepository, never()).findById(anyString());
+ verify(this.userContractRepository, never()).findEntityById(anyString());
assertNotNull(actual);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_IDENTIFIER_ERROR_MESSAGE), actual.getMessage());
@@ -404,12 +400,12 @@ void shouldThrowUserServiceFailureExceptionWhenInvalidUserIdProvidedOnChangePass
@Test
void shouldChangeUsernameAndPersistTheChange() {
String newUsername = "newUsername";
- when(this.userRepository.findById(USER_UUID)).thenReturn(this.user);
+ when(this.userContractRepository.findEntityById(USER_UUID)).thenReturn(this.user);
this.userService.changeUserName(USER_UUID, newUsername);
- verify(this.userRepository, times(1)).findById(USER_UUID);
- verify(this.userRepository, times(1)).save(this.userCaptor.capture());
+ verify(this.userContractRepository, times(1)).findEntityById(USER_UUID);
+ verify(this.userContractRepository, times(1)).persist(this.userCaptor.capture());
assertNotNull(userCaptor.getValue());
User updatedUser = userCaptor.getValue();
@@ -426,8 +422,8 @@ void shouldThrowUserServiceFailureExceptionWhenNewUsernameIsNull() {
UserServiceFailureException exception = assertThrows(UserServiceFailureException.class,
() -> this.userService.changeUserName(USER_UUID, null));
- verify(this.userRepository, never()).findById(USER_UUID);
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).findEntityById(USER_UUID);
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(exception);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.USERNAME_INVALID_ERROR_MESSAGE), exception.getMessage());
@@ -440,8 +436,8 @@ void shouldThrowUserServiceFailureExceptionWhenNewUsernameIsEmpty() {
UserServiceFailureException exception = assertThrows(UserServiceFailureException.class,
() -> this.userService.changeUserName(USER_UUID, newUsername));
- verify(this.userRepository, never()).findById(USER_UUID);
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, never()).findEntityById(USER_UUID);
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(exception);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.USERNAME_INVALID_ERROR_MESSAGE), exception.getMessage());
@@ -450,13 +446,13 @@ void shouldThrowUserServiceFailureExceptionWhenNewUsernameIsEmpty() {
@Test
void shouldThrowUserServiceFailureExceptionWhenUserNotFoundOnChangeUsername() {
String newUsername = "newUsername";
- when(this.userRepository.findById(USER_UUID)).thenReturn(null);
+ when(this.userContractRepository.findEntityById(USER_UUID)).thenReturn(null);
UserServiceFailureException exception = assertThrows(UserServiceFailureException.class,
() -> this.userService.changeUserName(USER_UUID, newUsername));
- verify(this.userRepository, times(1)).findById(USER_UUID);
- verify(this.userRepository, never()).save(any(UserContract.class));
+ verify(this.userContractRepository, times(1)).findEntityById(USER_UUID);
+ verify(this.userContractRepository, never()).persist(any(UserContract.class));
assertNotNull(exception);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.USER_NOT_FOUND_MESSAGE), exception.getMessage());
@@ -468,7 +464,7 @@ void shouldThrowUserServiceFailureExceptionWhenNullUserIdProvidedOnChangeUsernam
UserServiceFailureException actual = assertThrows(UserServiceFailureException.class,
() -> this.userService.changeUserName(null, "newUsername"));
- verify(this.userRepository, never()).findById(anyString());
+ verify(this.userContractRepository, never()).findEntityById(anyString());
assertNotNull(actual);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_IDENTIFIER_ERROR_MESSAGE), actual.getMessage());
@@ -480,7 +476,7 @@ void shouldThrowUserServiceFailureExceptionWhenEmptyUserIdProvidedOnChangeUserna
UserServiceFailureException actual = assertThrows(UserServiceFailureException.class,
() -> this.userService.changeUserName(" ", "newUsername"));
- verify(this.userRepository, never()).findById(anyString());
+ verify(this.userContractRepository, never()).findEntityById(anyString());
assertNotNull(actual);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_IDENTIFIER_ERROR_MESSAGE), actual.getMessage());
@@ -492,7 +488,7 @@ void shouldThrowUserServiceFailureExceptionWhenInvalidUserIdProvidedOnChangeUser
UserServiceFailureException actual = assertThrows(UserServiceFailureException.class,
() -> this.userService.changeUserName("ID", "newUsername"));
- verify(this.userRepository, never()).findById(anyString());
+ verify(this.userContractRepository, never()).findEntityById(anyString());
assertNotNull(actual);
assertEquals(UserServiceFailureException.ERROR.buildMessage(UserService.INVALID_IDENTIFIER_ERROR_MESSAGE), actual.getMessage());
diff --git a/src/test/java/diegosneves/github/conectardoacoes/core/utils/ValidationUtilsTest.java b/src/test/java/diegosneves/github/conectardoacoes/core/utils/ValidationUtilsTest.java
index 1cbe45d..fb3e5ec 100644
--- a/src/test/java/diegosneves/github/conectardoacoes/core/utils/ValidationUtilsTest.java
+++ b/src/test/java/diegosneves/github/conectardoacoes/core/utils/ValidationUtilsTest.java
@@ -28,7 +28,7 @@ void setUp() {
void isNullOrEmpty() {
this.value = "Teste";
try {
- ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.value, EMPTY_VALUE_ERROR, IllegalArgumentException.class);
+ ValidationUtils.validateNotNullOrEmpty(this.value, EMPTY_VALUE_ERROR, IllegalArgumentException.class);
} catch (Exception e) {
fail(UNEXPECTED_EXCEPTION);
}
@@ -38,7 +38,7 @@ void isNullOrEmpty() {
void checkStringNotNull() {
this.value = null;
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
- () -> ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.value, NULL_VALUE_ERROR_MESSAGE, IllegalArgumentException.class));
+ () -> ValidationUtils.validateNotNullOrEmpty(this.value, NULL_VALUE_ERROR_MESSAGE, IllegalArgumentException.class));
assertNotNull(exception);
assertEquals(NULL_VALUE_ERROR_MESSAGE, exception.getMessage());
@@ -49,7 +49,7 @@ void checkStringNotNullWithValidateUtilsException() {
this.value = null;
ValidationUtilsException exception = assertThrows(ValidationUtilsException.class,
- () -> ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.value, NULL_VALUE_ERROR_MESSAGE, NoMethodFoundException.class));
+ () -> ValidationUtils.validateNotNullOrEmpty(this.value, NULL_VALUE_ERROR_MESSAGE, NoMethodFoundException.class));
assertNotNull(exception);
assertEquals(ValidationUtilsException.ERROR.buildMessage(NoMethodFoundException.class.getSimpleName()), exception.getMessage());
@@ -59,7 +59,7 @@ void checkStringNotNullWithValidateUtilsException() {
void checkStringNotEmptyWithValidateUtilsException() {
ValidationUtilsException exception = assertThrows(ValidationUtilsException.class,
- () -> ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.value, EMPTY_VALUE_ERROR, NoMethodFoundException.class));
+ () -> ValidationUtils.validateNotNullOrEmpty(this.value, EMPTY_VALUE_ERROR, NoMethodFoundException.class));
assertNotNull(exception);
assertEquals(ValidationUtilsException.ERROR.buildMessage(NoMethodFoundException.class.getSimpleName()), exception.getMessage());
@@ -68,7 +68,7 @@ void checkStringNotEmptyWithValidateUtilsException() {
@Test
void checkStringNotEmpty() {
IllegalArgumentException exception = assertThrows(IllegalArgumentException.class,
- () -> ValidationUtils.checkNotNullAndNotEmptyOrThrowException(this.value, EMPTY_VALUE_ERROR, IllegalArgumentException.class));
+ () -> ValidationUtils.validateNotNullOrEmpty(this.value, EMPTY_VALUE_ERROR, IllegalArgumentException.class));
assertNotNull(exception);
assertEquals(EMPTY_VALUE_ERROR, exception.getMessage());