From d643020465efe63a12f231fb20fbecac29a3072d Mon Sep 17 00:00:00 2001 From: Rajbir Singh Date: Mon, 7 Oct 2024 15:53:26 +0200 Subject: [PATCH 01/10] PMT-16: Add Endpoint Specification --- api/pmt.yml | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/api/pmt.yml b/api/pmt.yml index 8c70a51..e8576fa 100644 --- a/api/pmt.yml +++ b/api/pmt.yml @@ -27,9 +27,56 @@ components: type: array items: $ref: "#/components/schemas/ProjectInfo" + CreateProjectDTO: + type: object + properties: + name: + type: string + goal: + type: string + customerId: + type: integer + format: int64 + administratorId: + type: integer + format: int64 + start: + type: string + format: date-time + plannedEnd: + type: string + format: date-time + CreatedProjectDTO: + type: object + properties: + id: + type: integer + format: int64 + name: + type: string + goal: + type: string + customerId: + type: integer + format: int64 + administratorId: + type: integer + format: int64 + start: + type: string + format: date-time + plannedEnd: + type: string + format: date-time responses: - UnAuthorized: - description: "Un Authorized" + Unauthorized: + description: "Unauthorized" + NotFound: + description: "Not Found" + content: + text/plain: + schema: + type: string InternalError: description: "Internal Server Error" content: @@ -49,7 +96,28 @@ paths: schema: $ref: "#/components/schemas/GetAllProjectsDTO" 401: - $ref: "#/components/responses/UnAuthorized" + $ref: "#/components/responses/Unauthorized" + 500: + $ref: "#/components/responses/InternalError" + post: + operationId: "CreateProject" + description: "Creates a new Project" + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/CreateProjectDTO" + responses: + 201: + description: "Project created successfully" + content: + application/json: + schema: + $ref: "#/components/schemas/CreatedProjectDTO" + 401: + $ref: "#/components/responses/Unauthorized" + 404: + $ref: "#/components/responses/NotFound" 500: $ref: "#/components/responses/InternalError" From 90125b7b14d6472248b22de24e47eb1122c1cbe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20S=C3=A4ume?= Date: Mon, 7 Oct 2024 15:54:06 +0200 Subject: [PATCH 02/10] PMT-16: Add More Errors to Endpoint Specification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dominik Säume --- api/pmt.yml | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/api/pmt.yml b/api/pmt.yml index e8576fa..3b22c8e 100644 --- a/api/pmt.yml +++ b/api/pmt.yml @@ -77,12 +77,30 @@ components: text/plain: schema: type: string + Conflict: + description: "Conflict" + content: + text/plain: + schema: + type: string + UnprocessableContent: + description: "Unprocessable Content" + content: + text/plain: + schema: + type: string InternalError: description: "Internal Server Error" content: text/plain: schema: type: string + ServiceUnavailable: + description: "Service Unavailable" + content: + text/plain: + schema: + type: string paths: /project: get: @@ -118,9 +136,16 @@ paths: $ref: "#/components/responses/Unauthorized" 404: $ref: "#/components/responses/NotFound" + 409: + $ref: "#/components/responses/Conflict" + 422: + $ref: "#/components/responses/UnprocessableContent" 500: $ref: "#/components/responses/InternalError" - + 503: + $ref: "#/components/responses/ServiceUnavailable" + + /project/{id}: delete: operationId: "deleteProject" @@ -136,7 +161,7 @@ paths: 204: description: "Deletes a specific Project" 401: - $ref: "#/components/responses/UnAuthorized" + $ref: "#/components/responses/Unauthorized" 404: description: "Project not found" content: From f8c802b18790d70ab8cd1338b19738e34b5f65fe Mon Sep 17 00:00:00 2001 From: Rajbir Singh Date: Mon, 7 Oct 2024 15:55:53 +0200 Subject: [PATCH 03/10] PMT-16: Add Method to Check if Project with Name Exists to ProjectRepository --- src/main/java/de/hmmh/pmt/db/ProjectRepository.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/de/hmmh/pmt/db/ProjectRepository.java b/src/main/java/de/hmmh/pmt/db/ProjectRepository.java index ef501dc..bb02ece 100644 --- a/src/main/java/de/hmmh/pmt/db/ProjectRepository.java +++ b/src/main/java/de/hmmh/pmt/db/ProjectRepository.java @@ -3,4 +3,5 @@ package de.hmmh.pmt.db; import org.springframework.data.jpa.repository.JpaRepository; public interface ProjectRepository extends JpaRepository { + boolean existsByName(String name); } From 94700b15b9fc209c09e7228274e0623ac2df46f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20S=C3=A4ume?= Date: Mon, 7 Oct 2024 15:56:38 +0200 Subject: [PATCH 04/10] PMT-16: Add Mapper for Project Creation/Created DTO to/from Project Entity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dominik Säume --- src/main/java/de/hmmh/pmt/util/Mapper.java | 32 ++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/main/java/de/hmmh/pmt/util/Mapper.java diff --git a/src/main/java/de/hmmh/pmt/util/Mapper.java b/src/main/java/de/hmmh/pmt/util/Mapper.java new file mode 100644 index 0000000..d5d7591 --- /dev/null +++ b/src/main/java/de/hmmh/pmt/util/Mapper.java @@ -0,0 +1,32 @@ +package de.hmmh.pmt.util; + +import de.hmmh.pmt.db.Project; +import de.hmmh.pmt.dtos.CreateProjectDTO; +import de.hmmh.pmt.dtos.CreatedProjectDTO; +import org.springframework.stereotype.Component; + +@Component +public class Mapper { + public Project map(CreateProjectDTO dto) { + Project project = new Project(); + project.setName(dto.getName()); + project.setGoal(dto.getGoal()); + project.setCustomerId(dto.getCustomerId()); + project.setAdministratorId(dto.getAdministratorId()); + project.setStart(dto.getStart()); + project.setPlannedEnd(dto.getPlannedEnd()); + return project; + } + + public CreatedProjectDTO map(Project project) { + CreatedProjectDTO dto = new CreatedProjectDTO(); + dto.setId(project.getId()); + dto.setName(project.getName()); + dto.setGoal(project.getGoal()); + dto.setCustomerId(project.getCustomerId()); + dto.setAdministratorId(project.getAdministratorId()); + dto.setStart(project.getStart()); + dto.setPlannedEnd(project.getPlannedEnd()); + return dto; + } +} From 118797258a22e21d568a72c62a23b1ff39f8478c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20S=C3=A4ume?= Date: Mon, 7 Oct 2024 15:57:02 +0200 Subject: [PATCH 05/10] PMT-16: Add Validation for Time Range to Project Entity MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dominik Säume --- src/main/java/de/hmmh/pmt/db/Project.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/hmmh/pmt/db/Project.java b/src/main/java/de/hmmh/pmt/db/Project.java index 9c9891f..c66731a 100644 --- a/src/main/java/de/hmmh/pmt/db/Project.java +++ b/src/main/java/de/hmmh/pmt/db/Project.java @@ -19,7 +19,7 @@ import java.time.LocalDateTime; @Table(name = "project") public class Project { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) + @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @NotBlank @@ -43,5 +43,10 @@ public class Project { private LocalDateTime plannedEnd; private LocalDateTime realEnd; // Cant be named just "end" because it's and SQL Keyword + + + public boolean isValid() { + return plannedEnd.isAfter(start) && (realEnd == null || realEnd.isAfter(start)); + } } From 5b601d20d7a220e9859ee6a41bfd61c65ff8428a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20S=C3=A4ume?= Date: Mon, 7 Oct 2024 15:58:38 +0200 Subject: [PATCH 06/10] PMT-16: Implement New Endpoint Logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rajbir Singh Signed-off-by: Dominik Säume --- src/main/java/de/hmmh/pmt/ApiController.java | 44 +++++++++++++++++--- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/hmmh/pmt/ApiController.java b/src/main/java/de/hmmh/pmt/ApiController.java index bc05059..51799b5 100644 --- a/src/main/java/de/hmmh/pmt/ApiController.java +++ b/src/main/java/de/hmmh/pmt/ApiController.java @@ -1,29 +1,35 @@ package de.hmmh.pmt; import com.fasterxml.jackson.databind.ObjectMapper; -import de.hmmh.pmt.employee.ApiClientFactory; import de.hmmh.pmt.db.Project; import de.hmmh.pmt.db.ProjectRepository; -import de.hmmh.pmt.oas.DefaultApi; +import de.hmmh.pmt.dtos.CreateProjectDTO; +import de.hmmh.pmt.dtos.CreatedProjectDTO; import de.hmmh.pmt.dtos.GetAllProjectsDTO; import de.hmmh.pmt.dtos.ProjectInfo; +import de.hmmh.pmt.employee.ApiClientFactory; +import de.hmmh.pmt.oas.DefaultApi; +import de.hmmh.pmt.util.Mapper; import jakarta.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestClientException; import java.util.Optional; @Controller @RequestMapping("${openapi.projectManagement.base-path:/api/v1}") public class ApiController implements DefaultApi { + @Autowired + private Mapper mapper; @Autowired private ApiClientFactory apiClientFactory; @Autowired private ProjectRepository projectRepository; - - // apiClientFactory.getEmployeeApi().findAll1() @Override public Optional getObjectMapper() { @@ -49,7 +55,7 @@ public class ApiController implements DefaultApi { public ResponseEntity getAllProjects() { GetAllProjectsDTO response = new GetAllProjectsDTO(); - for (Project project : this.projectRepository.findAll()){ + for (Project project : this.projectRepository.findAll()) { ProjectInfo projectInfo = new ProjectInfo(); projectInfo.setId(project.getId()); projectInfo.setName(project.getName()); @@ -58,4 +64,32 @@ public class ApiController implements DefaultApi { return ResponseEntity.ok(response); } + + @Override + public ResponseEntity createProject(CreateProjectDTO body) { + if (projectRepository.existsByName(body.getName())) { + return new ResponseEntity<>(HttpStatus.CONFLICT); + } + + try { + apiClientFactory.getEmployeeApi().findById(body.getAdministratorId()); + } catch (HttpClientErrorException exception) { + return new ResponseEntity<>( + exception.getStatusCode().equals(HttpStatus.NOT_FOUND) + ? HttpStatus.NOT_FOUND + : HttpStatus.SERVICE_UNAVAILABLE + ); + } catch (RestClientException exception) { + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + } + + Project project = mapper.map(body); + if (!project.isValid()) { + return new ResponseEntity<>(HttpStatus.UNPROCESSABLE_ENTITY); + } + projectRepository.save(project); + + CreatedProjectDTO response = mapper.map(project); + return new ResponseEntity<>(response, HttpStatus.CREATED); + } } From 7fb6b7524fa12f1f978f3e31d5dc4ad2742d949a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20S=C3=A4ume?= Date: Wed, 9 Oct 2024 09:58:43 +0200 Subject: [PATCH 07/10] PMT-16: Update Manual Validation Method of Projects to Include the builtin. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dominik Säume --- src/main/java/de/hmmh/pmt/db/Project.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/hmmh/pmt/db/Project.java b/src/main/java/de/hmmh/pmt/db/Project.java index c66731a..0a70189 100644 --- a/src/main/java/de/hmmh/pmt/db/Project.java +++ b/src/main/java/de/hmmh/pmt/db/Project.java @@ -1,6 +1,9 @@ package de.hmmh.pmt.db; import jakarta.persistence.*; +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; @@ -10,6 +13,7 @@ import lombok.NoArgsConstructor; import lombok.Setter; import java.time.LocalDateTime; +import java.util.Set; @NoArgsConstructor @AllArgsConstructor @@ -46,7 +50,13 @@ public class Project { public boolean isValid() { - return plannedEnd.isAfter(start) && (realEnd == null || realEnd.isAfter(start)); + Validator validator = Validation.buildDefaultValidatorFactory().getValidator(); + Set> violations = validator.validate(this); + + return violations.isEmpty() && + plannedEnd.isAfter(start) && + (realEnd == null || realEnd.isAfter(start)); } + } From 37048dab6ee9a9060670cd1c62af6cba43732b37 Mon Sep 17 00:00:00 2001 From: Rajbir Singh Date: Fri, 11 Oct 2024 17:00:14 +0200 Subject: [PATCH 08/10] PMT-16: Testing Create Project Endpoint --- .../java/de/hmmh/pmt/project/CreateTest.java | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 src/test/java/de/hmmh/pmt/project/CreateTest.java diff --git a/src/test/java/de/hmmh/pmt/project/CreateTest.java b/src/test/java/de/hmmh/pmt/project/CreateTest.java new file mode 100644 index 0000000..111d09b --- /dev/null +++ b/src/test/java/de/hmmh/pmt/project/CreateTest.java @@ -0,0 +1,105 @@ +package de.hmmh.pmt.project; + +import de.hmmh.pmt.IntegrationTest; +import de.hmmh.pmt.dtos.CreateProjectDTO; +import de.hmmh.pmt.employee.dtos.EmployeeResponseDTO; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.MediaType; +import org.springframework.test.web.servlet.RequestBuilder; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.web.client.HttpClientErrorException; + +import java.time.LocalDateTime; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +public class CreateTest extends IntegrationTest { + + @Test + void successfullyCreate() throws Exception { + when(this.mockEmployeeApi.findById(Mockito.anyLong())) + .thenReturn(new EmployeeResponseDTO()); + + CreateProjectDTO createDTO = new CreateProjectDTO(); + createDTO.setName("Test"); + createDTO.setGoal("A Test Goal"); + createDTO.setCustomerId(10L); + createDTO.setAdministratorId(10L); + createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); + createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); + + RequestBuilder requestBuilder = MockMvcRequestBuilders + .post(baseUri + "/project") + .accept(MediaType.APPLICATION_JSON) + .content(this.objectMapper.writeValueAsString(createDTO)) + .contentType(MediaType.APPLICATION_JSON); + + this.mvc + .perform(requestBuilder) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").exists()); + } + + @Test + void shouldNotCreateProjectWithSameName() throws Exception { + + CreateProjectDTO createDTO = new CreateProjectDTO(); + createDTO.setName("Test"); + createDTO.setGoal("A Test Goal"); + createDTO.setCustomerId(10L); + createDTO.setAdministratorId(1L); + createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); + createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); + + RequestBuilder firstProjectRequestBuilder = createProjectRequestBuilder(createDTO); + + this.mvc + .perform(firstProjectRequestBuilder) + .andExpect(status().isCreated()) + .andExpect(jsonPath("$.id").exists()); + + RequestBuilder secondProjectRequestBuilder = createProjectRequestBuilder(createDTO); + + this.mvc + .perform(secondProjectRequestBuilder) + .andExpect(status().isConflict()); + } + + @Test + void shouldNotCreateProjectWhenAdministratorDoesNotExist() throws Exception { + HttpClientErrorException httpClientErrorException = mock(HttpClientErrorException.class); + + when(httpClientErrorException.getStatusCode()).thenReturn(HttpStatusCode.valueOf(404)); + + when(this.mockEmployeeApi.findById(1L)) + .thenThrow(httpClientErrorException); + + CreateProjectDTO createDTO = new CreateProjectDTO(); + createDTO.setName("Test"); + createDTO.setGoal("A Test Goal"); + createDTO.setCustomerId(10L); + createDTO.setAdministratorId(1L); + createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); + createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); + + RequestBuilder projectRequestBuilder = createProjectRequestBuilder(createDTO); + + this.mvc + .perform(projectRequestBuilder) + .andExpect(status().isNotFound()); + } + + private RequestBuilder createProjectRequestBuilder(CreateProjectDTO createDTO) throws Exception { + + return MockMvcRequestBuilders + .post(baseUri + "/project") + .accept(MediaType.APPLICATION_JSON) + .content(this.objectMapper.writeValueAsString(createDTO)) + .contentType(MediaType.APPLICATION_JSON); + } +} From a1710ef2fac539f667322865c2430b98aef6bdd9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20K=C3=BCck?= Date: Mon, 14 Oct 2024 10:58:41 +0200 Subject: [PATCH 09/10] PMT-16: Edit and create more test cases --- .../java/de/hmmh/pmt/project/CreateTest.java | 105 ++++++++++++------ 1 file changed, 73 insertions(+), 32 deletions(-) diff --git a/src/test/java/de/hmmh/pmt/project/CreateTest.java b/src/test/java/de/hmmh/pmt/project/CreateTest.java index 111d09b..f17ac70 100644 --- a/src/test/java/de/hmmh/pmt/project/CreateTest.java +++ b/src/test/java/de/hmmh/pmt/project/CreateTest.java @@ -1,17 +1,21 @@ package de.hmmh.pmt.project; import de.hmmh.pmt.IntegrationTest; +import de.hmmh.pmt.db.Project; import de.hmmh.pmt.dtos.CreateProjectDTO; import de.hmmh.pmt.employee.dtos.EmployeeResponseDTO; import org.junit.jupiter.api.Test; import org.mockito.Mockito; +import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestClientException; import java.time.LocalDateTime; +import java.util.Map; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -33,14 +37,8 @@ public class CreateTest extends IntegrationTest { createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); - RequestBuilder requestBuilder = MockMvcRequestBuilders - .post(baseUri + "/project") - .accept(MediaType.APPLICATION_JSON) - .content(this.objectMapper.writeValueAsString(createDTO)) - .contentType(MediaType.APPLICATION_JSON); - this.mvc - .perform(requestBuilder) + .perform(getRequest(createDTO)) .andExpect(status().isCreated()) .andExpect(jsonPath("$.id").exists()); } @@ -48,36 +46,27 @@ public class CreateTest extends IntegrationTest { @Test void shouldNotCreateProjectWithSameName() throws Exception { + Map allProjects = createTestProjectData(); + Project spaceStation = allProjects.get("space-station"); + CreateProjectDTO createDTO = new CreateProjectDTO(); - createDTO.setName("Test"); - createDTO.setGoal("A Test Goal"); - createDTO.setCustomerId(10L); - createDTO.setAdministratorId(1L); - createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); - createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); - - RequestBuilder firstProjectRequestBuilder = createProjectRequestBuilder(createDTO); + createDTO.setName(spaceStation.getName()); + createDTO.setGoal(spaceStation.getGoal()); + createDTO.setCustomerId(spaceStation.getCustomerId()); + createDTO.setAdministratorId(spaceStation.getAdministratorId()); + createDTO.setStart(spaceStation.getStart()); + createDTO.setPlannedEnd(spaceStation.getPlannedEnd()); this.mvc - .perform(firstProjectRequestBuilder) - .andExpect(status().isCreated()) - .andExpect(jsonPath("$.id").exists()); - - RequestBuilder secondProjectRequestBuilder = createProjectRequestBuilder(createDTO); - - this.mvc - .perform(secondProjectRequestBuilder) + .perform(getRequest(createDTO)) .andExpect(status().isConflict()); } @Test void shouldNotCreateProjectWhenAdministratorDoesNotExist() throws Exception { - HttpClientErrorException httpClientErrorException = mock(HttpClientErrorException.class); - when(httpClientErrorException.getStatusCode()).thenReturn(HttpStatusCode.valueOf(404)); - - when(this.mockEmployeeApi.findById(1L)) - .thenThrow(httpClientErrorException); + when(this.mockEmployeeApi.findById(Mockito.anyLong())) + .thenThrow(new HttpClientErrorException(HttpStatus.NOT_FOUND)); CreateProjectDTO createDTO = new CreateProjectDTO(); createDTO.setName("Test"); @@ -87,14 +76,66 @@ public class CreateTest extends IntegrationTest { createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); - RequestBuilder projectRequestBuilder = createProjectRequestBuilder(createDTO); - this.mvc - .perform(projectRequestBuilder) + .perform(getRequest(createDTO)) .andExpect(status().isNotFound()); } - private RequestBuilder createProjectRequestBuilder(CreateProjectDTO createDTO) throws Exception { + @Test + void shouldReturnUnavailableWhenEmployeeApiIsDown() throws Exception { + + when(this.mockEmployeeApi.findById(Mockito.anyLong())) + .thenThrow(new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR)); + + CreateProjectDTO createDTO = new CreateProjectDTO(); + createDTO.setName("Test"); + createDTO.setGoal("A Test Goal"); + createDTO.setCustomerId(10L); + createDTO.setAdministratorId(1L); + createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); + createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); + + this.mvc + .perform(getRequest(createDTO)) + .andExpect(status().isServiceUnavailable()); + } + + @Test + void shouldReturnInternalServerErrorOnApiClientCrash() throws Exception { + + when(this.mockEmployeeApi.findById(Mockito.anyLong())) + .thenThrow(new RestClientException("Api Client crash")); + + CreateProjectDTO createDTO = new CreateProjectDTO(); + createDTO.setName("Test"); + createDTO.setGoal("A Test Goal"); + createDTO.setCustomerId(10L); + createDTO.setAdministratorId(1L); + createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); + createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); + + this.mvc + .perform(getRequest(createDTO)) + .andExpect(status().isInternalServerError()); + } + + @Test + void shouldReturnUnprocessableWhenDataIsInvalid() throws Exception { + + CreateProjectDTO createDTO = new CreateProjectDTO(); + createDTO.setName("Test"); + createDTO.setGoal("A Test Goal"); + createDTO.setCustomerId(10L); + createDTO.setAdministratorId(1L); + createDTO.setStart(LocalDateTime.of(2003, 1, 13, 12, 51)); + createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); + + this.mvc + .perform(getRequest(createDTO)) + .andExpect(status().isUnprocessableEntity()); + } + + private RequestBuilder getRequest(CreateProjectDTO createDTO) throws Exception { return MockMvcRequestBuilders .post(baseUri + "/project") From 50d889820d7cb0eda394e3ac95809cb43dffa3ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20K=C3=BCck?= Date: Mon, 14 Oct 2024 11:07:48 +0200 Subject: [PATCH 10/10] PMT-16: Cleanup Test Cases --- .../java/de/hmmh/pmt/project/CreateTest.java | 75 +++++-------------- 1 file changed, 17 insertions(+), 58 deletions(-) diff --git a/src/test/java/de/hmmh/pmt/project/CreateTest.java b/src/test/java/de/hmmh/pmt/project/CreateTest.java index f17ac70..1b162b3 100644 --- a/src/test/java/de/hmmh/pmt/project/CreateTest.java +++ b/src/test/java/de/hmmh/pmt/project/CreateTest.java @@ -1,5 +1,4 @@ package de.hmmh.pmt.project; - import de.hmmh.pmt.IntegrationTest; import de.hmmh.pmt.db.Project; import de.hmmh.pmt.dtos.CreateProjectDTO; @@ -7,17 +6,13 @@ import de.hmmh.pmt.employee.dtos.EmployeeResponseDTO; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatusCode; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.RequestBuilder; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestClientException; - import java.time.LocalDateTime; import java.util.Map; - -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -29,33 +24,19 @@ public class CreateTest extends IntegrationTest { when(this.mockEmployeeApi.findById(Mockito.anyLong())) .thenReturn(new EmployeeResponseDTO()); - CreateProjectDTO createDTO = new CreateProjectDTO(); - createDTO.setName("Test"); - createDTO.setGoal("A Test Goal"); - createDTO.setCustomerId(10L); - createDTO.setAdministratorId(10L); - createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); - createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); - this.mvc - .perform(getRequest(createDTO)) + .perform(getRequest(getCreateProjectDTO())) .andExpect(status().isCreated()) .andExpect(jsonPath("$.id").exists()); } @Test void shouldNotCreateProjectWithSameName() throws Exception { - Map allProjects = createTestProjectData(); Project spaceStation = allProjects.get("space-station"); - CreateProjectDTO createDTO = new CreateProjectDTO(); + CreateProjectDTO createDTO = getCreateProjectDTO(); createDTO.setName(spaceStation.getName()); - createDTO.setGoal(spaceStation.getGoal()); - createDTO.setCustomerId(spaceStation.getCustomerId()); - createDTO.setAdministratorId(spaceStation.getAdministratorId()); - createDTO.setStart(spaceStation.getStart()); - createDTO.setPlannedEnd(spaceStation.getPlannedEnd()); this.mvc .perform(getRequest(createDTO)) @@ -64,69 +45,37 @@ public class CreateTest extends IntegrationTest { @Test void shouldNotCreateProjectWhenAdministratorDoesNotExist() throws Exception { - when(this.mockEmployeeApi.findById(Mockito.anyLong())) .thenThrow(new HttpClientErrorException(HttpStatus.NOT_FOUND)); - CreateProjectDTO createDTO = new CreateProjectDTO(); - createDTO.setName("Test"); - createDTO.setGoal("A Test Goal"); - createDTO.setCustomerId(10L); - createDTO.setAdministratorId(1L); - createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); - createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); - this.mvc - .perform(getRequest(createDTO)) + .perform(getRequest(getCreateProjectDTO())) .andExpect(status().isNotFound()); } @Test void shouldReturnUnavailableWhenEmployeeApiIsDown() throws Exception { - when(this.mockEmployeeApi.findById(Mockito.anyLong())) .thenThrow(new HttpClientErrorException(HttpStatus.INTERNAL_SERVER_ERROR)); - CreateProjectDTO createDTO = new CreateProjectDTO(); - createDTO.setName("Test"); - createDTO.setGoal("A Test Goal"); - createDTO.setCustomerId(10L); - createDTO.setAdministratorId(1L); - createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); - createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); - this.mvc - .perform(getRequest(createDTO)) + .perform(getRequest(getCreateProjectDTO())) .andExpect(status().isServiceUnavailable()); } @Test void shouldReturnInternalServerErrorOnApiClientCrash() throws Exception { - when(this.mockEmployeeApi.findById(Mockito.anyLong())) .thenThrow(new RestClientException("Api Client crash")); - CreateProjectDTO createDTO = new CreateProjectDTO(); - createDTO.setName("Test"); - createDTO.setGoal("A Test Goal"); - createDTO.setCustomerId(10L); - createDTO.setAdministratorId(1L); - createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); - createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); - this.mvc - .perform(getRequest(createDTO)) + .perform(getRequest(getCreateProjectDTO())) .andExpect(status().isInternalServerError()); } @Test void shouldReturnUnprocessableWhenDataIsInvalid() throws Exception { - - CreateProjectDTO createDTO = new CreateProjectDTO(); - createDTO.setName("Test"); - createDTO.setGoal("A Test Goal"); - createDTO.setCustomerId(10L); - createDTO.setAdministratorId(1L); + CreateProjectDTO createDTO = getCreateProjectDTO(); createDTO.setStart(LocalDateTime.of(2003, 1, 13, 12, 51)); createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); @@ -135,8 +84,18 @@ public class CreateTest extends IntegrationTest { .andExpect(status().isUnprocessableEntity()); } - private RequestBuilder getRequest(CreateProjectDTO createDTO) throws Exception { + private CreateProjectDTO getCreateProjectDTO() { + CreateProjectDTO createDTO = new CreateProjectDTO(); + createDTO.setName("Test"); + createDTO.setGoal("A Test Goal"); + createDTO.setCustomerId(10L); + createDTO.setAdministratorId(10L); + createDTO.setStart(LocalDateTime.of(2000, 1, 13, 12, 51)); + createDTO.setPlannedEnd(LocalDateTime.of(2002, 3, 21, 11, 42)); + return createDTO; + } + private RequestBuilder getRequest(CreateProjectDTO createDTO) throws Exception { return MockMvcRequestBuilders .post(baseUri + "/project") .accept(MediaType.APPLICATION_JSON)