From 5a914bfea17ea925cb5f5041b5204a2e0cf94ca2 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Mon, 20 May 2019 16:23:52 +0300 Subject: [PATCH 01/28] feature/ba-0054: Added CustomerRequestStageName --- .../ba/entity/CustomerRequestStageName.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java diff --git a/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java b/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java new file mode 100644 index 0000000..491a860 --- /dev/null +++ b/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java @@ -0,0 +1,28 @@ +package io.khasang.ba.entity; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.hibernate.annotations.NaturalId; + +import javax.persistence.*; + +/** + * A customer request stage name entity class. Allows to group customer request stages by names. Has one-to-many + * relation with {@link CustomerRequestStage} + */ + +@Data +@Entity +@Table(name = "customer_request_stage_names") +public class CustomerRequestStageName { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @EqualsAndHashCode.Exclude + private Long id; + + @NaturalId + private String name; + + private String description; +} From e97db8fd42d8509093e35af580d83f1ea87caebf Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Mon, 20 May 2019 19:41:04 +0300 Subject: [PATCH 02/28] feature/ba-0054: Added CustomerRequestStageName REST layer (DAO + Service + Controller) --- .../java/io/khasang/ba/config/AppConfig.java | 5 ++ .../CustomerRequestStageNameController.java | 54 ++++++++++++++ .../ba/dao/CustomerRequestStageNameDao.java | 7 ++ .../impl/CustomerRequestStageNameDaoImpl.java | 11 +++ .../ba/entity/CustomerRequestStageName.java | 4 +- .../CustomerRequestStageNameService.java | 50 +++++++++++++ .../CustomerRequestStageNameServiceImpl.java | 73 +++++++++++++++++++ 7 files changed, 202 insertions(+), 2 deletions(-) create mode 100644 rest/src/main/java/io/khasang/ba/controller/CustomerRequestStageNameController.java create mode 100644 rest/src/main/java/io/khasang/ba/dao/CustomerRequestStageNameDao.java create mode 100644 rest/src/main/java/io/khasang/ba/dao/impl/CustomerRequestStageNameDaoImpl.java create mode 100644 rest/src/main/java/io/khasang/ba/service/CustomerRequestStageNameService.java create mode 100644 rest/src/main/java/io/khasang/ba/service/impl/CustomerRequestStageNameServiceImpl.java diff --git a/rest/src/main/java/io/khasang/ba/config/AppConfig.java b/rest/src/main/java/io/khasang/ba/config/AppConfig.java index aa2a580..c6043d4 100644 --- a/rest/src/main/java/io/khasang/ba/config/AppConfig.java +++ b/rest/src/main/java/io/khasang/ba/config/AppConfig.java @@ -110,4 +110,9 @@ public CategoryDao categoryDao() { public CustomerRequestStageDao customerRequestStageDao() { return new CustomerRequestStageDaoImpl(CustomerRequestStage.class); } + + @Bean + public CustomerRequestStageNameDao customerRequestStageNameDao() { + return new CustomerRequestStageNameDaoImpl(CustomerRequestStageName.class); + } } diff --git a/rest/src/main/java/io/khasang/ba/controller/CustomerRequestStageNameController.java b/rest/src/main/java/io/khasang/ba/controller/CustomerRequestStageNameController.java new file mode 100644 index 0000000..0edb67d --- /dev/null +++ b/rest/src/main/java/io/khasang/ba/controller/CustomerRequestStageNameController.java @@ -0,0 +1,54 @@ +package io.khasang.ba.controller; + +import io.khasang.ba.entity.CustomerRequestStageName; +import io.khasang.ba.service.CustomerRequestStageNameService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * Controller for REST layer of CustomerRequestStageName management: provided POST, GET, PUT and DELETE functionality + */ +@RestController +@RequestMapping(value = "/customer_request_stage_name") +// TODO ControllerAdvice and throwing of an exception in service layer +public class CustomerRequestStageNameController { + + @Autowired + private CustomerRequestStageNameService CustomerRequestStageNameService; + + @PostMapping(value = "/add", consumes = "application/json;charset=utf-8") + @ResponseStatus(HttpStatus.CREATED) + public CustomerRequestStageName addCustomerRequestStageName(@RequestBody CustomerRequestStageName newCustomerRequestStageName) { + return CustomerRequestStageNameService.addCustomerRequestStageName(newCustomerRequestStageName); + } + + @GetMapping(value = "/get/{id}") + public ResponseEntity getCustomerRequestStageNameById(@PathVariable(value = "id") long id) { + CustomerRequestStageName CustomerRequestStageName = CustomerRequestStageNameService.getCustomerRequestStageNameById(id); + + return CustomerRequestStageName != null ? + ResponseEntity.ok(CustomerRequestStageName) : ResponseEntity.notFound().build(); + } + + @PutMapping(value = "/update", consumes = "application/json;charset=utf-8") + // TODO Check updating of nonexistent entity + public CustomerRequestStageName updateCustomerRequestStageName(@RequestBody CustomerRequestStageName updatedCustomerRequestStageName) { + return CustomerRequestStageNameService.updateCustomerRequestStageName(updatedCustomerRequestStageName); + } + + @GetMapping(value = "/get/all") + public List getAllCustomerRequestStageNames() { + return CustomerRequestStageNameService.getAllCustomerRequestStageNames(); + } + + @DeleteMapping(value = "/delete/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + // TODO Check DELETE non-existent entity + public void deleteCustomerRequestStageName(@PathVariable(value = "id") long id) { + CustomerRequestStageNameService.deleteCustomerRequestStageName(id); + } +} diff --git a/rest/src/main/java/io/khasang/ba/dao/CustomerRequestStageNameDao.java b/rest/src/main/java/io/khasang/ba/dao/CustomerRequestStageNameDao.java new file mode 100644 index 0000000..c484ee1 --- /dev/null +++ b/rest/src/main/java/io/khasang/ba/dao/CustomerRequestStageNameDao.java @@ -0,0 +1,7 @@ +package io.khasang.ba.dao; + + +import io.khasang.ba.entity.CustomerRequestStageName; + +public interface CustomerRequestStageNameDao extends BasicDao { +} \ No newline at end of file diff --git a/rest/src/main/java/io/khasang/ba/dao/impl/CustomerRequestStageNameDaoImpl.java b/rest/src/main/java/io/khasang/ba/dao/impl/CustomerRequestStageNameDaoImpl.java new file mode 100644 index 0000000..6458ca8 --- /dev/null +++ b/rest/src/main/java/io/khasang/ba/dao/impl/CustomerRequestStageNameDaoImpl.java @@ -0,0 +1,11 @@ +package io.khasang.ba.dao.impl; + +import io.khasang.ba.dao.CustomerRequestStageNameDao; +import io.khasang.ba.entity.CustomerRequestStageName; + +public class CustomerRequestStageNameDaoImpl extends BasicDaoImpl + implements CustomerRequestStageNameDao { + public CustomerRequestStageNameDaoImpl(Class entityClass) { + super(entityClass); + } +} \ No newline at end of file diff --git a/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java b/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java index 491a860..336adaa 100644 --- a/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java +++ b/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java @@ -7,8 +7,8 @@ import javax.persistence.*; /** - * A customer request stage name entity class. Allows to group customer request stages by names. Has one-to-many - * relation with {@link CustomerRequestStage} + * A customer request stage name entity class. Allows to group customer request stages by names, i.e. + * each {@link CustomerRequestStage} has a relation with this entity. */ @Data diff --git a/rest/src/main/java/io/khasang/ba/service/CustomerRequestStageNameService.java b/rest/src/main/java/io/khasang/ba/service/CustomerRequestStageNameService.java new file mode 100644 index 0000000..976bca7 --- /dev/null +++ b/rest/src/main/java/io/khasang/ba/service/CustomerRequestStageNameService.java @@ -0,0 +1,50 @@ +package io.khasang.ba.service; + +import io.khasang.ba.entity.CustomerRequestStageName; + +import java.util.List; + +/** + * Service layer interface for {@link CustomerRequestStageName} management + */ +public interface CustomerRequestStageNameService { + + /** + * Add new CustomerRequestStageName + * + * @param newCustomerRequestStageName New instance of CustomerRequestStageName + * @return Added {@link CustomerRequestStageName} instance + */ + CustomerRequestStageName addCustomerRequestStageName(CustomerRequestStageName newCustomerRequestStageName); + + /** + * Get CustomerRequestStageName by id + * + * @param id Identifier of the desired CustomerRequestStageName + * @return Found {@link CustomerRequestStageName} instance + */ + CustomerRequestStageName getCustomerRequestStageNameById(long id); + + /** + * Update existing CustomerRequestStageName with new instance + * + * @param updatedCustomerRequestStageName Updated CustomerRequestStageName instance + * @return Updated {@link CustomerRequestStageName} instance + */ + CustomerRequestStageName updateCustomerRequestStageName(CustomerRequestStageName updatedCustomerRequestStageName); + + /** + * Get all CustomerRequestStageNames + * + * @return {@link List} instance of all CustomerRequestStageNames + */ + List getAllCustomerRequestStageNames(); + + /** + * Delete CustomerRequestStageName by id + * + * @param id Identifier of the CustomerRequestStageName which should be deleted + * @return Deleted {@link CustomerRequestStageName} instance + */ + CustomerRequestStageName deleteCustomerRequestStageName(long id); +} \ No newline at end of file diff --git a/rest/src/main/java/io/khasang/ba/service/impl/CustomerRequestStageNameServiceImpl.java b/rest/src/main/java/io/khasang/ba/service/impl/CustomerRequestStageNameServiceImpl.java new file mode 100644 index 0000000..44fff95 --- /dev/null +++ b/rest/src/main/java/io/khasang/ba/service/impl/CustomerRequestStageNameServiceImpl.java @@ -0,0 +1,73 @@ +package io.khasang.ba.service.impl; + +import io.khasang.ba.dao.CustomerRequestStageNameDao; +import io.khasang.ba.entity.CustomerRequestStageName; +import io.khasang.ba.service.CustomerRequestStageNameService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * Implementation of {@link CustomerRequestStageNameService} based on DAO-layer utilization + */ +@Service +public class CustomerRequestStageNameServiceImpl implements CustomerRequestStageNameService { + + @Autowired + private CustomerRequestStageNameDao CustomerRequestStageNameDao; + + /** + * Add new CustomerRequestStageName + * + * @param newCustomerRequestStageName New instance of CustomerRequestStageName + * @return Added {@link CustomerRequestStageName} instance + */ + @Override + public CustomerRequestStageName addCustomerRequestStageName(CustomerRequestStageName newCustomerRequestStageName) { + return CustomerRequestStageNameDao.add(newCustomerRequestStageName); + } + + /** + * Get CustomerRequestStageName by id + * + * @param id Identifier of the desired CustomerRequestStageName + * @return Found {@link CustomerRequestStageName} instance + */ + @Override + public CustomerRequestStageName getCustomerRequestStageNameById(long id) { + return CustomerRequestStageNameDao.getById(id); + } + + /** + * Update existing CustomerRequestStageName with new instance + * + * @param updatedCustomerRequestStageName Updated CustomerRequestStageName instance + * @return Updated {@link CustomerRequestStageName} instance + */ + @Override + public CustomerRequestStageName updateCustomerRequestStageName(CustomerRequestStageName updatedCustomerRequestStageName) { + return CustomerRequestStageNameDao.update(updatedCustomerRequestStageName); + } + + /** + * Get all CustomerRequestStageNames + * + * @return {@link List} instance of all CustomerRequestStageNames + */ + @Override + public List getAllCustomerRequestStageNames() { + return CustomerRequestStageNameDao.getAll(); + } + + /** + * Delete CustomerRequestStageName by id + * + * @param id Identifier of the CustomerRequestStageName which should be deleted + * @return Deleted {@link CustomerRequestStageName} instance + */ + @Override + public CustomerRequestStageName deleteCustomerRequestStageName(long id) { + return CustomerRequestStageNameDao.delete(getCustomerRequestStageNameById(id)); + } +} From f4f7ce51e318dec08932d15d7af76b959fff182b Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Tue, 21 May 2019 19:26:26 +0300 Subject: [PATCH 03/28] feature/ba-0054: 1) Added CustomerRequestStageNameControllerIntegrationTest class. 2) CustomerRequestStageName#name annotated with @NotBlank. 3) Modified RestRequest: added automated REST resource detection by entity class (added restPathsMap); typeReferencesMap added, to automate detection of necessary ParameterizedTypeReference by class. 4) Modified MockFactory: added automated mock supplier detection by entity class (added mockSuppliersMap). --- ...RequestStageControllerIntegrationTest.java | 31 +-- ...estStageNameControllerIntegrationTest.java | 231 ++++++++++++++++++ .../ba/controller/utility/MockFactory.java | 64 +++-- .../ba/controller/utility/RestRequests.java | 186 ++++++++++---- .../ba/entity/CustomerRequestStageName.java | 4 +- 5 files changed, 431 insertions(+), 85 deletions(-) create mode 100644 integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageNameControllerIntegrationTest.java diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageControllerIntegrationTest.java index 3d51782..af9c40a 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageControllerIntegrationTest.java @@ -3,7 +3,6 @@ import io.khasang.ba.controller.utility.MockFactory; import io.khasang.ba.entity.CustomerRequestStage; import org.junit.Test; -import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpStatus; import java.time.LocalDateTime; @@ -32,7 +31,6 @@ public void checkGetNonExistentCustomerRequestStage() { getEntityById( Long.MAX_VALUE, CustomerRequestStage.class, - CUSTOMER_REQUEST_STAGE_ROOT + GET_BY_ID_PATH, HttpStatus.NOT_FOUND); } @@ -52,7 +50,6 @@ public void checkAddCustomerRequestStage() { CustomerRequestStage receivedCustomerRequestStage = getEntityById( createdCustomerRequestStage.getId(), CustomerRequestStage.class, - CUSTOMER_REQUEST_STAGE_ROOT + GET_BY_ID_PATH, HttpStatus.OK); assertEquals(createdCustomerRequestStage, receivedCustomerRequestStage); @@ -73,19 +70,15 @@ public void checkAddCustomerRequestStage() { public void checkGetAllCustomerRequestStages() { // Create list of entities - List createdCustomerRequestStagesList = getCreatedEntitiesList( - MockFactory::getMockCustomerRequestStage, - TEST_ENTITIES_AMOUNT, - CUSTOMER_REQUEST_STAGE_ROOT + ADD_PATH, - HttpStatus.CREATED); + List createdCustomerRequestStagesList = + getCreatedEntitiesList( + CustomerRequestStage.class, + TEST_ENTITIES_AMOUNT, + HttpStatus.CREATED); // Receive all entities from REST List allCustomerRequestStages = - getAllEntitiesList( - new ParameterizedTypeReference>() { - }, - CUSTOMER_REQUEST_STAGE_ROOT + GET_ALL_PATH, - HttpStatus.OK); + getAllEntitiesList(CustomerRequestStage.class, HttpStatus.OK); // Check last TEST_ENTITIES_AMOUNT and assert for equality List receivedCustomerRequestStagesSubList = @@ -109,7 +102,6 @@ public void checkUpdateCustomerRequestStage() { CustomerRequestStage receivedCustomerRequestStage = getEntityById( updatedCustomerRequestStage.getId(), CustomerRequestStage.class, - CUSTOMER_REQUEST_STAGE_ROOT + GET_BY_ID_PATH, HttpStatus.OK ); assertNotNull(receivedCustomerRequestStage.getId()); @@ -126,13 +118,11 @@ public void checkCustomerRequestStageDelete() { getResponseFromEntityDeleteRequest( createdCustomerRequestStage.getId(), CustomerRequestStage.class, - CUSTOMER_REQUEST_STAGE_ROOT + DELETE_BY_ID_PATH, HttpStatus.NO_CONTENT); assertNull(getEntityById( createdCustomerRequestStage.getId(), CustomerRequestStage.class, - CUSTOMER_REQUEST_STAGE_ROOT + GET_BY_ID_PATH, HttpStatus.NOT_FOUND)); } @@ -147,7 +137,6 @@ private CustomerRequestStage getCreatedCustomerRequestStage() { LocalDateTime timeBeforeCreation = LocalDateTime.now(); CustomerRequestStage createdCustomerRequestStage = getResponseFromEntityAddRequest( customerRequestStage, - CUSTOMER_REQUEST_STAGE_ROOT + ADD_PATH, HttpStatus.CREATED); LocalDateTime timeAfterCreation = LocalDateTime.now(); @@ -169,10 +158,10 @@ private CustomerRequestStage getUpdatedCustomerRequestStage() { CustomerRequestStage createdCustomerRequestStage = getCreatedCustomerRequestStage(); LocalDateTime timeBeforeUpdate = LocalDateTime.now(); - CustomerRequestStage updatedCustomerRequestStage = getResponseFromEntityUpdateRequest( - getChangedMockCustomerRequestStage(createdCustomerRequestStage), - CUSTOMER_REQUEST_STAGE_ROOT + UPDATE_PATH, - HttpStatus.OK); + CustomerRequestStage updatedCustomerRequestStage = + getResponseFromEntityUpdateRequest( + getChangedMockCustomerRequestStage(createdCustomerRequestStage), + HttpStatus.OK); LocalDateTime timeAfterUpdate = LocalDateTime.now(); assertEquals(createdCustomerRequestStage.getId(), updatedCustomerRequestStage.getId()); diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageNameControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageNameControllerIntegrationTest.java new file mode 100644 index 0000000..068000f --- /dev/null +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageNameControllerIntegrationTest.java @@ -0,0 +1,231 @@ +package io.khasang.ba.controller; + +import io.khasang.ba.controller.utility.MockFactory; +import io.khasang.ba.controller.utility.RestRequests; +import io.khasang.ba.entity.CustomerRequestStageName; +import org.junit.Test; +import org.springframework.http.HttpStatus; + +import java.util.List; + +import static io.khasang.ba.controller.utility.MockFactory.getChangedMockCustomerRequestStageName; +import static io.khasang.ba.controller.utility.MockFactory.getMockCustomerRequestStageName; +import static io.khasang.ba.controller.utility.RestRequests.*; +import static org.junit.Assert.*; + +/** + * Integration test for {@link CustomerRequestStageNameController} and {@link CustomerRequestStageName} REST layer. + * Utility classes {@link MockFactory} and {@link io.khasang.ba.controller.utility.RestRequests} are used. + */ +// TODO DELETE nonexistent +// TODO UPDATE nonexistent +// TODO provide Error messages +public class CustomerRequestStageNameControllerIntegrationTest { + + /** + * Check, that {@link CustomerRequestStageNameController#getCustomerRequestStageNameById(long)} gives NOT FOUND HTTP response + * in the case of attempt to get nonexistent entity, i.e. entity with nonexistent Id. + */ + @Test + public void checkGetNonExistentCustomerRequestStageName() { + getEntityById(Long.MAX_VALUE, CustomerRequestStageName.class, HttpStatus.NOT_FOUND); + } + + /** + * Check both {@link CustomerRequestStageNameController#getCustomerRequestStageNameById(long)} and + * {@link CustomerRequestStageNameController#addCustomerRequestStageName(CustomerRequestStageName)} methods, + * i.e. HTTP methods GET and POST, providing possibilities to get an {@link CustomerRequestStageName} entity + * from REST resource and to add it to the resource. + */ + @Test + public void checkAddCustomerRequestStageName() { + + //POST to REST + CustomerRequestStageName createdCustomerRequestStageName = getCreatedCustomerRequestStageName(); + + // GET from REST + CustomerRequestStageName receivedCustomerRequestStageName = + getEntityById( + createdCustomerRequestStageName.getId(), + CustomerRequestStageName.class, + HttpStatus.OK); + + assertEquals(createdCustomerRequestStageName, receivedCustomerRequestStageName); + } + + /** + * Check {@link CustomerRequestStageNameController#getAllCustomerRequestStageNames()} method, i.e. HTTP method GET, used to + * get a list of {@link CustomerRequestStageName} entities from REST resource + * entities.
+ *

First of all, continuous addition of {@link CustomerRequestStageName} entities with amount equal to + * {@link io.khasang.ba.controller.utility.RestRequests#TEST_ENTITIES_AMOUNT} is performed. + * Secondly, top TEST_ENTITIES_AMOUNT of entities, obtained from response body, received from REST-resource, placed at + * {@link io.khasang.ba.controller.utility.RestRequests#GET_ALL_PATH}), compared with list of + * previously added entities. + *

+ */ + @Test + public void checkGetAllCustomerRequestStageNames() { + + // Create list of entities + List createdCustomerRequestStageNamesList = + getCreatedEntitiesList( + CustomerRequestStageName.class, + RestRequests.TEST_ENTITIES_AMOUNT, + HttpStatus.CREATED); + + // Receive all entities from REST + List allCustomerRequestStageNames = + getAllEntitiesList(CustomerRequestStageName.class, HttpStatus.OK); + + // Check last TEST_ENTITIES_AMOUNT and assert for equality + List receivedCustomerRequestStageNamesSubList = + allCustomerRequestStageNames.subList(allCustomerRequestStageNames.size() - TEST_ENTITIES_AMOUNT, + allCustomerRequestStageNames.size()); + + assertEquals(createdCustomerRequestStageNamesList, receivedCustomerRequestStageNamesSubList); + } + + /** + * Check {@link CustomerRequestStageNameController#updateCustomerRequestStageName(CustomerRequestStageName)}, i.e. HTTP method + * PUT, used to update an {@link CustomerRequestStageName} entity on REST resource + */ + @Test + public void checkUpdateCustomerRequestStageName() { + + // POST, then UPDATE in REST + CustomerRequestStageName updatedCustomerRequestStageName = getUpdatedCustomerRequestStageName(); + + //Get it from REST, check id and assertEquals + CustomerRequestStageName receivedCustomerRequestStageName = + getEntityById( + updatedCustomerRequestStageName.getId(), + CustomerRequestStageName.class, + HttpStatus.OK); + + assertNotNull(receivedCustomerRequestStageName.getId()); + assertEquals(updatedCustomerRequestStageName, receivedCustomerRequestStageName); + } + + /** + * Check {@link CustomerRequestStageNameController#deleteCustomerRequestStageName(long)}, i.e. HTTP method + * DELETE, used to delete an {@link CustomerRequestStageName} entity on REST resource + */ + @Test + public void checkCustomerRequestStageNameDelete() { + CustomerRequestStageName createdCustomerRequestStageName = getCreatedCustomerRequestStageName(); + getResponseFromEntityDeleteRequest( + createdCustomerRequestStageName.getId(), + CustomerRequestStageName.class, + HttpStatus.NO_CONTENT); + + assertNull(getEntityById( + createdCustomerRequestStageName.getId(), + CustomerRequestStageName.class, + HttpStatus.NOT_FOUND)); + } + + /** + * Check unique constraint for name field while adding {@link CustomerRequestStageName} + */ + @Test + public void checkUniqueConstraintForName_whenCustomerRequestStageAdd() { + addWithIncorrectField("name", getCreatedCustomerRequestStageName().getName()); + } + + /** + * Check not blank constraint for name while adding {@link CustomerRequestStageName} + */ + @Test + public void checkNotBlankConstraintForName_whenCustomerRequestStageAdd() { + addWithIncorrectField("name", null); + addWithIncorrectField("name", ""); + addWithIncorrectField("name", " "); + addWithIncorrectField("name", " "); + addWithIncorrectField("name", "\t"); + addWithIncorrectField("name", "\n"); + } + + /** + * Check unique constraint for name while updating {@link CustomerRequestStageName} + */ + @Test + public void checkUniqueConstraintForName_whenCustomerRequestStageUpdate() { + updateWithIncorrectField("name", getCreatedCustomerRequestStageName().getName()); + } + + /** + * Check not blank constraint for name while updating {@link CustomerRequestStageName} + */ + @Test + public void checkNotBlankNameConstraintForName_whenCustomerRequestStageUpdate() { + updateWithIncorrectField("name", null); + updateWithIncorrectField("name", ""); + updateWithIncorrectField("name", " "); + updateWithIncorrectField("name", " "); + updateWithIncorrectField("name", "\t"); + updateWithIncorrectField("name", "\n"); + } + + /** + * Create mock {@link CustomerRequestStageName} instance, and add (i.e. POST) it to a REST resource + * + * @return added to REST resource entity + */ + private CustomerRequestStageName getCreatedCustomerRequestStageName() { + CustomerRequestStageName customerRequestStageName = getMockCustomerRequestStageName(); + + CustomerRequestStageName createdCustomerRequestStageName = + getResponseFromEntityAddRequest(customerRequestStageName, HttpStatus.CREATED); + + assertNotNull(createdCustomerRequestStageName.getId()); + assertEquals(customerRequestStageName, createdCustomerRequestStageName); + + return createdCustomerRequestStageName; + } + + /** + * Update existing {@link CustomerRequestStageName} entity at REST resource. Firstly, add new mock entity and then + * PUT updated entity to REST resource + * + * @return updated at REST resource instance of entity + */ + private CustomerRequestStageName getUpdatedCustomerRequestStageName() { + CustomerRequestStageName createdCustomerRequestStageName = getCreatedCustomerRequestStageName(); + + CustomerRequestStageName updatedCustomerRequestStageName = + getResponseFromEntityUpdateRequest( + getChangedMockCustomerRequestStageName(createdCustomerRequestStageName), + HttpStatus.OK); + + assertEquals(createdCustomerRequestStageName.getId(), updatedCustomerRequestStageName.getId()); + + return updatedCustomerRequestStageName; + } + + /** + * Utility method for checking of some constraints during entity addition, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link RestRequests#addEntityWithIncorrectField(Class, String, Object, HttpStatus)}. + * + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field + */ + private void addWithIncorrectField(String fieldName, V incorrectValue) { + addEntityWithIncorrectField(CustomerRequestStageName.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); + } + + /** + * Utility method for checking of some constraints during entity update, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link RestRequests#updateEntityWithIncorrectField(Class, String, Object, HttpStatus)}. + * + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field + */ + private void updateWithIncorrectField(String fieldName, V incorrectValue) { + updateEntityWithIncorrectField(CustomerRequestStageName.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); + } +} diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java index 0539d9e..c459904 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java @@ -4,11 +4,10 @@ import org.springframework.http.HttpStatus; import java.time.LocalDate; -import java.util.List; -import java.util.UUID; +import java.util.*; import java.util.function.Supplier; -import static io.khasang.ba.controller.utility.RestRequests.*; +import static io.khasang.ba.controller.utility.RestRequests.getCreatedEntitiesList; /** * Factory class providing automation of creating and changing mock entities @@ -20,6 +19,17 @@ public final class MockFactory { */ public static final int RELATED_ENTITIES_AMOUNT = 5; + /** + * Map which determines supplier for entity by entity class, therefore there is no necessity create mock entity directly, + * because its' supplier will be detected automatically + */ + public static final Map, Supplier> mockSuppliersMap = Collections.unmodifiableMap(new HashMap, Supplier>() {{ + put(Customer.class, MockFactory::getMockCustomer); + put(CustomerRequestStage.class, MockFactory::getMockCustomerRequestStage); + put(CustomerRequestStageName.class, MockFactory::getMockCustomerRequestStageName); + put(Operator.class, MockFactory::getMockOperator); + }}); + //Mock data for Customer private static final String TEST_CUSTOMER_LOGIN_PREFIX = "TEST_CUSTOMER_"; private static final String TEST_CUSTOMER_RAW_PASSWORD = "123tEsT#"; @@ -30,17 +40,6 @@ public final class MockFactory { private static final String TEST_CUSTOMER_CITY = "Saint Petersburg"; private static final String TEST_CUSTOMER_ABOUT = "Another one mock test customer"; - /** - * Ready-to-use mock {@link Customer} supplier - */ - public static final Supplier MOCK_CUSTOMER_SUPPLIER = MockFactory::getMockCustomer; - - /** - * Ready-to-use mock {@link CustomerRequestStage} supplier - */ - public static final Supplier MOCK_CUSTOMER_REQUEST_STAGE_SUPPLIER = - MockFactory::getMockCustomerRequestStage; - //Mock data for Operator private static final String TEST_OPERATOR_LOGIN_PREFIX = "TEST_OPERATOR_"; private static final String TEST_OPERATOR_RAW_PASSWORD = "123tEsT#"; @@ -54,6 +53,10 @@ public final class MockFactory { //Mock data for CustomerRequestStage private static final String TEST_CUSTOMER_REQUEST_STAGE_DESCRIPTION = "Test description of the customer's request stage"; + //Mock data for CustomerRequestStageName + private static final String TEST_CUSTOMER_REQUEST_STAGE_NAME_NAME_PREFIX = "TEST_STAGE_NAME_PREFIX_"; + private static final String TEST_CUSTOMER_REQUEST_STAGE_NAME_DESCRIPTION_PREFIX = "Customer's request stage name: "; + /** * Create mock {@link Customer} instance * @@ -109,9 +112,8 @@ public static CustomerRequestStage getMockCustomerRequestStage() { CustomerRequestStage customerRequestStage = new CustomerRequestStage(); List operatorList = getCreatedEntitiesList( - MockFactory::getMockOperator, + Operator.class, RELATED_ENTITIES_AMOUNT, - OPERATOR_ROOT + ADD_PATH, HttpStatus.OK); customerRequestStage.setComment(TEST_CUSTOMER_REQUEST_STAGE_DESCRIPTION); @@ -135,4 +137,34 @@ public static CustomerRequestStage getChangedMockCustomerRequestStage(CustomerRe return newCustomerRequestStage; } + + /** + * Create mock {@link CustomerRequestStageName} instance + * + * @return mock {@link CustomerRequestStageName} instance + */ + public static CustomerRequestStageName getMockCustomerRequestStageName() { + CustomerRequestStageName customerRequestStageName = new CustomerRequestStageName(); + + customerRequestStageName.setName(TEST_CUSTOMER_REQUEST_STAGE_NAME_NAME_PREFIX + UUID.randomUUID().toString()); + customerRequestStageName.setDescription(TEST_CUSTOMER_REQUEST_STAGE_NAME_DESCRIPTION_PREFIX + + UUID.randomUUID().toString()); + + return customerRequestStageName; + } + + /** + * Change existing {@link CustomerRequestStageName}. Firstly, new mock entity is made and then copying of necessary + * fields from old entity (generally with constraints Id, Unique, NaturalId etc) is performed. + * + * @param oldCustomerRequestStageName old entity + * @return changed entity + */ + public static CustomerRequestStageName getChangedMockCustomerRequestStageName(CustomerRequestStageName oldCustomerRequestStageName) { + CustomerRequestStageName newCustomerRequestStageName = getMockCustomerRequestStageName(); + + newCustomerRequestStageName.setId(oldCustomerRequestStageName.getId()); + + return newCustomerRequestStageName; + } } diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java index 1dae4b0..54fa0f7 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java @@ -1,5 +1,8 @@ package io.khasang.ba.controller.utility; +import io.khasang.ba.entity.CustomerRequestStage; +import io.khasang.ba.entity.CustomerRequestStageName; +import io.khasang.ba.entity.Operator; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.web.client.HttpClientErrorException; @@ -7,7 +10,10 @@ import org.springframework.web.client.RestTemplate; import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -32,6 +38,7 @@ public final class RestRequests { // Roots of REST resources public static final String CUSTOMER_REQUEST_STAGE_ROOT = REST_ROOT + "customer_request_stage"; + public static final String CUSTOMER_REQUEST_STAGE_NAME_ROOT = REST_ROOT + "customer_request_stage_name"; public static final String OPERATOR_ROOT = REST_ROOT + "operator"; // Common addresses of REST resources @@ -41,68 +48,89 @@ public final class RestRequests { public static final String UPDATE_PATH = "/update"; public static final String DELETE_BY_ID_PATH = "/delete/{id}"; + /** + * Map which determines root of rest resources by entity class, therefore there is no necessity to specify path + * of the REST resource, because it will be detected automatically + */ + public static final Map, String> restRootsMap = Collections.unmodifiableMap(new HashMap, String>() {{ + put(CustomerRequestStage.class, CUSTOMER_REQUEST_STAGE_ROOT); + put(CustomerRequestStageName.class, CUSTOMER_REQUEST_STAGE_NAME_ROOT); + put(Operator.class, OPERATOR_ROOT); + }}); + + /** + * Map which determines maps class to parametrized type reference for lists of entities in order to avoid boilerplate code + */ + public static final Map, ParameterizedTypeReference> typeReferencesMap = + new HashMap, ParameterizedTypeReference>() {{ + put(CustomerRequestStage.class, new ParameterizedTypeReference>() { + }); + put(CustomerRequestStageName.class, new ParameterizedTypeReference>() { + }); + put(Operator.class, new ParameterizedTypeReference>() { + }); + }}; + /** * Add an entity via POST HTTP-method, check status codes of response, provide necessary assertions, - * and return body of the response + * and return body of the response. Path to corresponding REST resource is detected by class by means of {@link #restRootsMap} * * @param entity the entity, which should be added - * @param postUrl an URL of receiving POST request REST-resource * @param expectedStatusCode expected HTTP status code of response * @param type of the entity both of request and response * @return POST response body */ - public static T getResponseFromEntityAddRequest(T entity, String postUrl, HttpStatus expectedStatusCode) { - return getBodyOfResponseToSendEntityRequest(entity, postUrl, HttpMethod.POST, expectedStatusCode); + public static T getResponseFromEntityAddRequest(T entity, HttpStatus expectedStatusCode) { + return getBodyOfResponseToSendEntityRequest(entity, restRootsMap.get(entity.getClass()) + ADD_PATH, + HttpMethod.POST, expectedStatusCode); } /** * Get an entity via GET HTTP-method, check status codes of response, provide necessary assertions, - * and return body of the response + * and return body of the response. Path to corresponding REST resource is detected by class by means of {@link #restRootsMap} * * @param id of an entity which should be found * @param entityClass class of the desired entity - * @param getUrl an URL of receiving GET request REST-resource * @param expectedStatusCode expected HTTP status code of response * @param type of the entity returned in response body * @return GET response body, i.e. entity instance */ - public static T getEntityById(Long id, Class entityClass, String getUrl, HttpStatus expectedStatusCode) { + public static T getEntityById(Long id, Class entityClass, HttpStatus expectedStatusCode) { return tryToGetResponseBody(() -> { ResponseEntity responseEntity = new RestTemplate().exchange( - getUrl, + restRootsMap.get(entityClass) + GET_BY_ID_PATH, HttpMethod.GET, null, entityClass, id); assertEquals(expectedStatusCode, responseEntity.getStatusCode()); - T entity1 = responseEntity.getBody(); - assertNotNull(entity1); + T responseBody = responseEntity.getBody(); + assertNotNull(responseBody); - return entity1; + return responseBody; }, expectedStatusCode); } /** * Get all entities via GET HTTP-method, check status codes of response, provide necessary assertions, - * and return body of the response + * and return body of the response. Path to corresponding REST resource is detected by class by means of {@link #restRootsMap}
+ * Also, {@link #typeReferencesMap} used, to automate detection of necessary {@link ParameterizedTypeReference} by class. * * @param type of entities list returned in response body - * @param getAllUrl an URL of receiving GET request REST-resource * @param expectedStatusCode expected HTTP status code of response * @return list of all entities from the given resource */ - public static List getAllEntitiesList(ParameterizedTypeReference> typeReference, String getAllUrl, + @SuppressWarnings("unchecked") + public static List getAllEntitiesList(Class entityClass, HttpStatus expectedStatusCode) { return tryToGetResponseBody(() -> { - RestTemplate restTemplate = new RestTemplate(); - - ResponseEntity> responseEntity = restTemplate.exchange( - getAllUrl, + ResponseEntity> responseEntity = new RestTemplate().exchange( + restRootsMap.get(entityClass) + GET_ALL_PATH, HttpMethod.GET, null, - typeReference + (ParameterizedTypeReference>) typeReferencesMap.get(entityClass) ); assertEquals(expectedStatusCode, responseEntity.getStatusCode()); @@ -117,37 +145,39 @@ public static List getAllEntitiesList(ParameterizedTypeReference> /** * Update an entity via POST HTTP-method, check status codes of response, provide necessary assertions, - * and return body of the response + * and return body of the response. Path to corresponding REST resource is detected by class by means of {@link #restRootsMap} * * @param entity the entity, which should be added - * @param putUrl an URL of receiving POST request REST-resource * @param expectedStatusCode expected HTTP status code of response * @param type of the entity both of request and response * @return PUT response body */ - public static T getResponseFromEntityUpdateRequest(T entity, String putUrl, HttpStatus expectedStatusCode) { - T putEntity = getBodyOfResponseToSendEntityRequest(entity, putUrl, HttpMethod.PUT, expectedStatusCode); + public static T getResponseFromEntityUpdateRequest(T entity, HttpStatus expectedStatusCode) { + T putEntity = getBodyOfResponseToSendEntityRequest( + entity, + restRootsMap.get(entity.getClass()) + UPDATE_PATH, + HttpMethod.PUT, + expectedStatusCode); + assertEquals(entity, putEntity); return putEntity; } /** * Delete an entity via DELETE HTTP-method, check status codes of response, provide necessary assertions, - * and return body of the response + * and return body of the response. Path to corresponding REST resource is detected by class by means of {@link #restRootsMap} * * @param id identifier of the entity, which should be deleted * @param entityClass class of the entity - * @param deleteUrl an URL of receiving DELETE request REST-resource * @param expectedStatusCode expected HTTP status code of response * @param type of the entity in response body * @return DELETE response body */ - public static T getResponseFromEntityDeleteRequest(Long id, Class entityClass, String deleteUrl, + public static T getResponseFromEntityDeleteRequest(Long id, Class entityClass, HttpStatus expectedStatusCode) { return tryToGetResponseBody(() -> { - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( - deleteUrl, + ResponseEntity responseEntity = new RestTemplate().exchange( + restRootsMap.get(entityClass) + DELETE_BY_ID_PATH, HttpMethod.DELETE, null, entityClass, @@ -161,22 +191,24 @@ public static T getResponseFromEntityDeleteRequest(Long id, Class entityC } /** - * Perform continuous addition of entities, supplied with a given supplier, to REST resource. + * Perform continuous addition of group entities. Entities are created by a supplier, found by class, acting as key + * for {@link MockFactory#mockSuppliersMap}. Path of corresponding REST resource is detected + * in the same way by means of {@link #restRootsMap} * For example, the supplier could be a method link to {@link MockFactory#getMockCustomer()}):
. * MockFactory::getMockCustomer
* Each entity undergoes POST request to REST resource with a given URL * - * @param entitySupplier supplier of entities + * @param entityClass an entity class * @param amount amount of entities to create - * @param postUrl an URL of receiving POST request REST-resource * @param expectedStatusCode expected HTTP status code response to each POST request * @param type of entities both of request and response * @return list of the entities created on REST-resource */ - public static List getCreatedEntitiesList(Supplier entitySupplier, int amount, - String postUrl, HttpStatus expectedStatusCode) { + @SuppressWarnings("unchecked") + public static List getCreatedEntitiesList(Class entityClass, int amount, HttpStatus expectedStatusCode) { Function toEntityFromPostRequest = (T entity) -> - getResponseFromEntityAddRequest(entity, postUrl, expectedStatusCode); + getResponseFromEntityAddRequest(entity, expectedStatusCode); + Supplier entitySupplier = (Supplier) MockFactory.mockSuppliersMap.get(entityClass); return Stream .generate(entitySupplier) @@ -186,25 +218,86 @@ public static List getCreatedEntitiesList(Supplier entitySupplier, int } /** - * Check sending of an entity with incorrect field (with incorrect value or with violating constraint) to a given - * REST resource. Field is changed via java reflection mechanisms.
+ *

Check addition of an entity with incorrect field (with incorrect value or with violating such constraints, as NotNull, Unique) + * to corresponding REST resource, which path is detected by class by means of {@link #restRootsMap}. + * Field value is set via java reflection mechanisms.

+ *

In a case of absence of {@link HttpClientErrorException} or {@link HttpServerErrorException}, method fails with assertion error + * NOTICE: This behaviour will be changed after REST layer response codes regulation

+ * + * @param entityClass an entity class + * @param fieldName a field, which should be changed + * @param incorrectValue incorrect value for changing field + * @param expectedErrorStatusCode expected HTTP status code error + * @param type of the entity both of request and response + * @param type of the field + */ + @SuppressWarnings("unchecked") + public static void addEntityWithIncorrectField(Class entityClass, String fieldName, V incorrectValue, + HttpStatus expectedErrorStatusCode) { + Supplier entitySupplier = (Supplier) MockFactory.mockSuppliersMap.get(entityClass); + sendEntityWithIncorrectField( + entitySupplier.get(), + fieldName, + incorrectValue, + restRootsMap.get(entityClass) + ADD_PATH, + HttpMethod.POST, + expectedErrorStatusCode); + } + + /** + *

Check update of an entity with incorrect field (with incorrect value or with violating such constraints, as NotNull, Unique) + * at corresponding REST resource, which path is detected by class by means of {@link #restRootsMap}. + * Field value is set via java reflection mechanisms.

+ *

First of all, entity is properly created at REST resource, after that incorrect value is set to a given field and attempt + * to update REST resource is performed.

+ *

In a case of absence of {@link HttpClientErrorException} or {@link HttpServerErrorException}, method fails with assertion error + * NOTICE: This behaviour will be changed after REST layer response codes regulation

+ * + * @param entityClass an entity class + * @param fieldName a field, which should be changed + * @param incorrectValue incorrect value for changing field + * @param expectedErrorStatusCode expected HTTP status code error + * @param type of the entity both of request and response + * @param type of the field + */ + @SuppressWarnings("unchecked") + public static void updateEntityWithIncorrectField(Class entityClass, String fieldName, V incorrectValue, + HttpStatus expectedErrorStatusCode) { + Supplier entitySupplier = (Supplier) MockFactory.mockSuppliersMap.get(entityClass); + T entity = getResponseFromEntityAddRequest(entitySupplier.get(), HttpStatus.CREATED); + + sendEntityWithIncorrectField( + entity, + fieldName, + incorrectValue, + restRootsMap.get(entityClass) + UPDATE_PATH, + HttpMethod.PUT, + expectedErrorStatusCode); + } + + /** + * Check sending of an entity with incorrect field (with incorrect value or with violating such constraints, as NotNull, Unique) + * to a given REST resource. Field is changed via java reflection mechanisms.
* Method checks for expected exception and, in a case of its' absence, it will fail with assertion error * NOTICE: This behaviour will be changed after REST layer response codes regulation * - * @param entity an entity (eg. mock entity supplier) + * @param entity an entity, which should be sent * @param fieldName a field, which should be changed * @param incorrectValue incorrect value for changing field * @param url URL of receiving POST request REST-resource * @param expectedErrorStatusCode expected HTTP status code error * @param type of the entity both of request and response - * @param type of the filed + * @param type of the field */ - public static void sendEntityWithIncorrectField(T entity, String fieldName, V incorrectValue, String url, - HttpMethod httpMethod, HttpStatus expectedErrorStatusCode) - throws NoSuchFieldException, IllegalAccessException { - setField(entity, fieldName, incorrectValue); - getBodyOfResponseToSendEntityRequest(entity, url, httpMethod, expectedErrorStatusCode); - fail("No expected exception occurs during sending of an entity with incorrect field"); + private static void sendEntityWithIncorrectField(T entity, String fieldName, + V incorrectValue, String url, HttpMethod httpMethod, + HttpStatus expectedErrorStatusCode) { + try { + setField(entity, fieldName, incorrectValue); + getBodyOfResponseToSendEntityRequest(entity, url, httpMethod, expectedErrorStatusCode); + } catch (NoSuchFieldException | IllegalAccessException e) { + fail(e.toString()); + } } /** @@ -256,8 +349,7 @@ private static T getBodyOfResponseToSendEntityRequest(T entity, String url, httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); HttpEntity httpEntity = new HttpEntity<>(entity, httpHeaders); - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( + ResponseEntity responseEntity = new RestTemplate().exchange( url, httpMethod, httpEntity, diff --git a/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java b/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java index 336adaa..35e351e 100644 --- a/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java +++ b/rest/src/main/java/io/khasang/ba/entity/CustomerRequestStageName.java @@ -3,6 +3,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import org.hibernate.annotations.NaturalId; +import org.hibernate.validator.constraints.NotBlank; import javax.persistence.*; @@ -21,7 +22,8 @@ public class CustomerRequestStageName { @EqualsAndHashCode.Exclude private Long id; - @NaturalId + @NotBlank + @NaturalId(mutable = true) private String name; private String description; From 5be307d30a83ca882b2a0faa8c5b4d588e0e4ba6 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Wed, 22 May 2019 21:29:23 +0300 Subject: [PATCH 04/28] feature/ba-0100: Modified RestRequests and Mock factory in order to support Customer entity --- .../CustomerControllerIntegrationTest.java | 10 +++++ .../ba/controller/utility/MockFactory.java | 43 +++++++++++++------ .../ba/controller/utility/RestRequests.java | 3 ++ 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index 29825a9..3a1c1bc 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.UUID; +import static io.khasang.ba.controller.utility.RestRequests.getEntityById; import static org.junit.Assert.*; /** @@ -41,6 +42,15 @@ public class CustomerControllerIntegrationTest { private static final String UPDATE = "/update"; private static final String DELETE_BY_ID = "/delete/{id}"; + /** + * Check, that {@link CustomerController#getCustomerById(long)} gives NOT FOUND HTTP response + * in the case of attempt to get nonexistent entity, i.e. entity with nonexistent Id. + */ + @Test + public void checkGetNonExistentCustomer() { + getEntityById(Long.MAX_VALUE, Customer.class, HttpStatus.NOT_FOUND); + } + /** * Check customer addition */ diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java index c459904..f174793 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java @@ -32,13 +32,11 @@ public final class MockFactory { //Mock data for Customer private static final String TEST_CUSTOMER_LOGIN_PREFIX = "TEST_CUSTOMER_"; - private static final String TEST_CUSTOMER_RAW_PASSWORD = "123tEsT#"; private static final String TEST_CUSTOMER_EMAIL_SUFFIX = "@ba.khasang.io"; - private static final String TEST_CUSTOMER_FULL_NAME = "Ivan Petrov"; - private static final LocalDate TEST_CUSTOMER_BIRTHDATE = LocalDate.of(1986, 8, 26); - private static final String TEST_CUSTOMER_COUNTRY = "Russia"; - private static final String TEST_CUSTOMER_CITY = "Saint Petersburg"; - private static final String TEST_CUSTOMER_ABOUT = "Another one mock test customer"; + private static final String TEST_CUSTOMER_FULL_NAME_PREFIX = "Ivan Petrov "; + private static final String TEST_CUSTOMER_COUNTRY_PREFIX = "Russia "; + private static final String TEST_CUSTOMER_CITY_PREFIX = "Saint Petersburg "; + private static final String TEST_CUSTOMER_ABOUT_PREFIX = "Another one mock test customer"; //Mock data for Operator private static final String TEST_OPERATOR_LOGIN_PREFIX = "TEST_OPERATOR_"; @@ -63,23 +61,44 @@ public final class MockFactory { * @return mock customer instance */ public static Customer getMockCustomer() { + Random random = new Random(); Customer customer = new Customer(); CustomerInformation customerInformation = new CustomerInformation(); customer.setLogin(TEST_CUSTOMER_LOGIN_PREFIX + UUID.randomUUID().toString()); - customer.setPassword(TEST_CUSTOMER_RAW_PASSWORD); + customer.setPassword(UUID.randomUUID().toString()); customer.setEmail(UUID.randomUUID().toString() + TEST_CUSTOMER_EMAIL_SUFFIX); customer.setCustomerInformation(customerInformation); - customerInformation.setFullName(TEST_CUSTOMER_FULL_NAME); - customerInformation.setBirthDate(TEST_CUSTOMER_BIRTHDATE); - customerInformation.setCountry(TEST_CUSTOMER_COUNTRY); - customerInformation.setCity(TEST_CUSTOMER_CITY); - customerInformation.setAbout(TEST_CUSTOMER_ABOUT); + customerInformation.setFullName(TEST_CUSTOMER_FULL_NAME_PREFIX + UUID.randomUUID().toString()); + customerInformation.setBirthDate(LocalDate.of( + 1930 + random.nextInt(70), + 1 + random.nextInt(12), + 1 + random.nextInt(30))); + customerInformation.setCountry(TEST_CUSTOMER_COUNTRY_PREFIX + UUID.randomUUID().toString()); + customerInformation.setCity(TEST_CUSTOMER_CITY_PREFIX + UUID.randomUUID().toString()); + customerInformation.setAbout(TEST_CUSTOMER_ABOUT_PREFIX + UUID.randomUUID().toString()); return customer; } + /** + * Change existing {@link Customer}. Firstly, new mock entity is made and then copying of necessary + * fields from old entity (generally with constraints Id, Unique, NaturalId etc) is performed. + * + * @param oldCustomer old entity + * @return changed entity + */ + public static Customer getChangedMockCustomer(Customer oldCustomer) { + Customer newCustomer = getMockCustomer(); + + newCustomer.setId(oldCustomer.getId()); + newCustomer.setLogin(oldCustomer.getLogin()); + newCustomer.setRegistrationTimestamp(oldCustomer.getRegistrationTimestamp()); + + return newCustomer; + } + /** * Create mock {@link Operator} instance * diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java index 54fa0f7..802bc1d 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java @@ -1,5 +1,6 @@ package io.khasang.ba.controller.utility; +import io.khasang.ba.entity.Customer; import io.khasang.ba.entity.CustomerRequestStage; import io.khasang.ba.entity.CustomerRequestStageName; import io.khasang.ba.entity.Operator; @@ -37,6 +38,7 @@ public final class RestRequests { public static String REST_ROOT = "http://localhost:8080/"; // Roots of REST resources + public static final String CUSTOMER_ROOT = REST_ROOT + "customer"; public static final String CUSTOMER_REQUEST_STAGE_ROOT = REST_ROOT + "customer_request_stage"; public static final String CUSTOMER_REQUEST_STAGE_NAME_ROOT = REST_ROOT + "customer_request_stage_name"; public static final String OPERATOR_ROOT = REST_ROOT + "operator"; @@ -53,6 +55,7 @@ public final class RestRequests { * of the REST resource, because it will be detected automatically */ public static final Map, String> restRootsMap = Collections.unmodifiableMap(new HashMap, String>() {{ + put(Customer.class, CUSTOMER_ROOT); put(CustomerRequestStage.class, CUSTOMER_REQUEST_STAGE_ROOT); put(CustomerRequestStageName.class, CUSTOMER_REQUEST_STAGE_NAME_ROOT); put(Operator.class, OPERATOR_ROOT); From 9319c6cb526a6a72a6e92a52ab7b68cefe2b2339 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Wed, 22 May 2019 21:58:52 +0300 Subject: [PATCH 05/28] feature/ba-0100: 1) Added CustomerControllerIntegrationTest#checkGetNonExistentCustomer and modified CustomerController#getCustomerById method (status codes added), 2) CustomerController annotated with @RestController instead of @Controller, 3) Corresponding request mappings set to controller methods (@GetMapping, @postMapping etc) --- .../ba/controller/CustomerController.java | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/rest/src/main/java/io/khasang/ba/controller/CustomerController.java b/rest/src/main/java/io/khasang/ba/controller/CustomerController.java index c47f5e2..52a1454 100644 --- a/rest/src/main/java/io/khasang/ba/controller/CustomerController.java +++ b/rest/src/main/java/io/khasang/ba/controller/CustomerController.java @@ -3,7 +3,7 @@ import io.khasang.ba.entity.Customer; import io.khasang.ba.service.CustomerService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -11,39 +11,37 @@ /** * Controller for REST layer of Customer management: provided POST, GET, PUT and DELETE functionality */ -@Controller +@RestController @RequestMapping(value = "/customer") +// TODO ControllerAdvice and throwing of an exception in service layer public class CustomerController { @Autowired private CustomerService CustomerService; - @RequestMapping(value = "/add", method = RequestMethod.POST, produces = "application/json;charset=utf-8") - @ResponseBody + @PostMapping(value = "/add", consumes = "application/json;charset=utf-8") public Customer addCustomer(@RequestBody Customer newCustomer) { return CustomerService.addCustomer(newCustomer); } - @RequestMapping(value = "/get/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - @ResponseBody - public Customer getCustomerById(@PathVariable(value = "id") long id) { - return CustomerService.getCustomerById(id); + @GetMapping(value = "/get/{id}") + public ResponseEntity getCustomerById(@PathVariable(value = "id") long id) { + Customer customer = CustomerService.getCustomerById(id); + + return (customer != null) ? ResponseEntity.ok(customer) : ResponseEntity.notFound().build(); } - @RequestMapping(value = "/update", method = RequestMethod.PUT, produces = "application/json;charset=utf-8") - @ResponseBody + @PutMapping(value = "/update", consumes = "application/json;charset=utf-8") public Customer updateCustomer(@RequestBody Customer updatedCustomer) { return CustomerService.updateCustomer(updatedCustomer); } - @RequestMapping(value = "/get/all", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - @ResponseBody + @GetMapping(value = "/get/all") public List getAllCustomers() { return CustomerService.getAllCustomers(); } - @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE, produces = "application/json;charset=utf-8") - @ResponseBody + @DeleteMapping(value = "/delete/{id}") public Customer deleteCustomer(@PathVariable(value = "id") long id) { return CustomerService.deleteCustomer(id); } From 094b43d929b1c08324c42399d8dcc3fd2c7749f2 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 10:17:16 +0300 Subject: [PATCH 06/28] feature/ba-0100: 1) Modified CustomerControllerIntegrationTest#checkDeleteCustomer 2) CustomerController#addCustomer and CustomerController#deleteCustomer modified in order to return response codes 3) Fixed random birth date creation in MockFactory#getMockCustomer --- .../CustomerControllerIntegrationTest.java | 61 ++++++------------- .../ba/controller/utility/MockFactory.java | 7 +-- .../ba/controller/CustomerController.java | 7 ++- 3 files changed, 28 insertions(+), 47 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index 3a1c1bc..68328ca 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -10,12 +10,12 @@ import java.lang.reflect.Field; import java.time.LocalDate; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import java.util.UUID; -import static io.khasang.ba.controller.utility.RestRequests.getEntityById; +import static io.khasang.ba.controller.utility.MockFactory.getMockCustomer; +import static io.khasang.ba.controller.utility.RestRequests.*; import static org.junit.Assert.*; /** @@ -248,14 +248,22 @@ public void checkUpdateWithBlankPassword() { } /** - * Check of customer deletion + * Check {@link CustomerController#deleteCustomer(long)}, i.e. HTTP method + * DELETE, used to delete an {@link Customer} entity on REST resource */ @Test public void checkCustomerDelete() { - Customer customer = getCreatedCustomer(); - Customer deletedCustomer = getDeletedCustomer(customer.getId()); - assertEquals(customer, deletedCustomer); - assertNull(getCustomerById(customer.getId())); + Customer createdCustomer = getCreatedCustomer(); + + getResponseFromEntityDeleteRequest( + createdCustomer.getId(), + Customer.class, + HttpStatus.NO_CONTENT); + + assertNull(getEntityById( + createdCustomer.getId(), + Customer.class, + HttpStatus.NOT_FOUND)); } /** @@ -388,49 +396,20 @@ private Customer getChangedCustomer(Customer oldCustomer) { } /** - * Get created test customer entity from POST response during customer creation procedure. Instead of creating {@link Customer} - * instance by constructor, this method returns instance from response, thus created customer contains table identifier + * Create mock {@link Customer} instance, and add (i.e. POST) it to a REST resource * - * @return Instance of {@link Customer} with generated identifier + * @return added to REST resource entity */ private Customer getCreatedCustomer() { Customer customer = getMockCustomer(); - LocalDateTime timeBeforeCreation = LocalDateTime.now(); - ResponseEntity responseEntity = getResponseEntityFromPostRequest(customer); - Customer createdCustomer = responseEntity.getBody(); - LocalDateTime timeAfterCreation = LocalDateTime.now(); + Customer createdCustomer = + getResponseFromEntityAddRequest(customer, HttpStatus.CREATED); - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - assertNotNull(createdCustomer); assertNotNull(createdCustomer.getId()); assertEquals(customer, createdCustomer); - assertEquals(-1, timeBeforeCreation.compareTo(createdCustomer.getRegistrationTimestamp())); - assertEquals(1, timeAfterCreation.compareTo(createdCustomer.getRegistrationTimestamp())); - return createdCustomer; - } - /** - * Create mock {@link Customer} instance - * - * @return mock customer instance - */ - private Customer getMockCustomer() { - Customer customer = new Customer(); - CustomerInformation customerInformation = new CustomerInformation(); - - customer.setLogin(TEST_CUSTOMER_LOGIN_PREFIX + UUID.randomUUID().toString()); - customer.setPassword(TEST_CUSTOMER_RAW_PASSWORD); - customer.setEmail(UUID.randomUUID().toString() + TEST_CUSTOMER_EMAIL_SUFFIX); - customer.setCustomerInformation(customerInformation); - - customerInformation.setFullName(TEST_CUSTOMER_FULL_NAME); - customerInformation.setBirthDate(TEST_CUSTOMER_BIRTHDATE); - customerInformation.setCountry(TEST_CUSTOMER_COUNTRY); - customerInformation.setCity(TEST_CUSTOMER_CITY); - customerInformation.setAbout(TEST_CUSTOMER_ABOUT); - - return customer; + return createdCustomer; } /** diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java index f174793..77ad280 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java @@ -71,10 +71,9 @@ public static Customer getMockCustomer() { customer.setCustomerInformation(customerInformation); customerInformation.setFullName(TEST_CUSTOMER_FULL_NAME_PREFIX + UUID.randomUUID().toString()); - customerInformation.setBirthDate(LocalDate.of( - 1930 + random.nextInt(70), - 1 + random.nextInt(12), - 1 + random.nextInt(30))); + customerInformation.setBirthDate(LocalDate.ofYearDay( + 1930 + random.nextInt(71), + 1 + random.nextInt(365))); customerInformation.setCountry(TEST_CUSTOMER_COUNTRY_PREFIX + UUID.randomUUID().toString()); customerInformation.setCity(TEST_CUSTOMER_CITY_PREFIX + UUID.randomUUID().toString()); customerInformation.setAbout(TEST_CUSTOMER_ABOUT_PREFIX + UUID.randomUUID().toString()); diff --git a/rest/src/main/java/io/khasang/ba/controller/CustomerController.java b/rest/src/main/java/io/khasang/ba/controller/CustomerController.java index 52a1454..c7aa620 100644 --- a/rest/src/main/java/io/khasang/ba/controller/CustomerController.java +++ b/rest/src/main/java/io/khasang/ba/controller/CustomerController.java @@ -3,6 +3,7 @@ import io.khasang.ba.entity.Customer; import io.khasang.ba.service.CustomerService; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -20,6 +21,7 @@ public class CustomerController { private CustomerService CustomerService; @PostMapping(value = "/add", consumes = "application/json;charset=utf-8") + @ResponseStatus(HttpStatus.CREATED) public Customer addCustomer(@RequestBody Customer newCustomer) { return CustomerService.addCustomer(newCustomer); } @@ -42,7 +44,8 @@ public List getAllCustomers() { } @DeleteMapping(value = "/delete/{id}") - public Customer deleteCustomer(@PathVariable(value = "id") long id) { - return CustomerService.deleteCustomer(id); + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteCustomer(@PathVariable(value = "id") long id) { + CustomerService.deleteCustomer(id); } } From af44b4fc00faba798f8c22d5d045d03e825d7075 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 10:21:51 +0300 Subject: [PATCH 07/28] feature/ba-0100: Modified CustomerControllerIntegrationTest#checkAddCustomer --- .../CustomerControllerIntegrationTest.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index 68328ca..548bc50 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -52,13 +52,24 @@ public void checkGetNonExistentCustomer() { } /** - * Check customer addition + * Check both {@link CustomerController#getCustomerById(long)} and + * {@link CustomerController#addCustomer(Customer)} methods, + * i.e. HTTP methods GET and POST, providing possibilities to get an {@link Customer} entity + * from REST resource and to add it to the resource. */ @Test public void checkAddCustomer() { + + //POST to REST Customer createdCustomer = getCreatedCustomer(); - Customer receivedCustomer = getCustomerById(createdCustomer.getId()); - assertNotNull(receivedCustomer); + + // GET from REST + Customer receivedCustomer = + getEntityById( + createdCustomer.getId(), + Customer.class, + HttpStatus.OK); + assertEquals(createdCustomer, receivedCustomer); } From e0b387aac270258b845a475ddbc82bacdfdedca0 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 10:26:03 +0300 Subject: [PATCH 08/28] feature/ba-0100: Removed unnecessary CustomerControllerIntegrationTest#getDeletedCustomer --- .../CustomerControllerIntegrationTest.java | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index 548bc50..e6880f7 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -442,25 +442,4 @@ private ResponseEntity getResponseEntityFromPostRequest(Customer custo Customer.class ); } - - /** - * Utility method which deletes customer by id and retrieves customer entity from DELETE response body - * - * @param id Id of the customer which should be deleted - * @return Deleted customer - */ - private Customer getDeletedCustomer(Long id) { - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + DELETE_BY_ID, - HttpMethod.DELETE, - null, - Customer.class, - id - ); - Customer deletedCustomer = responseEntity.getBody(); - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - assertNotNull(deletedCustomer); - return deletedCustomer; - } } From 429b0a04e221c35fdd29c6f54e83715f7a5648b1 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 11:17:03 +0300 Subject: [PATCH 09/28] feature/ba-0100: Deleted old and added new methods for checking constraints for login, email and password fields --- .../CustomerControllerIntegrationTest.java | 154 ++++++++---------- 1 file changed, 66 insertions(+), 88 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index e6880f7..3830b05 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -73,76 +73,6 @@ public void checkAddCustomer() { assertEquals(createdCustomer, receivedCustomer); } - /** - * Check unique login constraint for customer's login during addition process - */ - @Test(expected = HttpServerErrorException.class) - public void checkAddLoginUniqueConstraint() { - Customer customer = getCreatedCustomer(); - Customer customerWithSameLogin = getMockCustomer(); - customerWithSameLogin.setLogin(customer.getLogin()); - getResponseEntityFromPostRequest(customerWithSameLogin); - } - - /** - * Check unique constraint for customer's e-mail during addition process - */ - @Test(expected = HttpServerErrorException.class) - public void checkAddEmailUniqueConstraint() { - Customer customer = getCreatedCustomer(); - Customer customerWithSameEmail = getMockCustomer(); - customerWithSameEmail.setEmail(customer.getEmail()); - getResponseEntityFromPostRequest(customerWithSameEmail); - } - - /** - * Check NotBlank(+ NotNull + NotEmpty) constraint for customer's login during addition process - */ - @Test - public void checkAddWithBlankLogin() { - - //NotNull + NotEmpty - addWithIncorrectField("login", null); - addWithIncorrectField("login", ""); - - //Check NotBlank (whitespaces and some other characters) - addWithIncorrectField("login", " "); - addWithIncorrectField("login", "\t"); - addWithIncorrectField("login", "\n"); - } - - /** - * Check NotBlank(+ NotNull + NotEmpty) constraint for customer's email during addition process - */ - @Test - public void checkAddWithBlankEmail() { - - //NotNull + NotEmpty - addWithIncorrectField("email", null); - addWithIncorrectField("email", ""); - - //Check NotBlank (whitespaces and some other characters) - addWithIncorrectField("email", " "); - addWithIncorrectField("email", "\t"); - addWithIncorrectField("email", "\n"); - } - - /** - * Check NotBlank(+ NotNull + NotEmpty) constraint for customer's password during addition process - */ - @Test - public void checkAddWithBlankPassword() { - - //NotNull + NotEmpty - addWithIncorrectField("password", null); - addWithIncorrectField("password", ""); - - //Check NotBlank (whitespaces and some other characters) - addWithIncorrectField("password", " "); - addWithIncorrectField("password", "\t"); - addWithIncorrectField("password", "\n"); - } - /** * Checks sequential addition of certain amount of customers addition and getting. Amount is set in * {@link #TEST_ENTITIES_COUNT} constant @@ -277,26 +207,61 @@ public void checkCustomerDelete() { HttpStatus.NOT_FOUND)); } + //Addition constraints + /** - * Utility method to check Customer entity addition with incorrect field (overriding mock value). - * Field is changed by Java reflections mechanisms.
- * Method checks that thrown exception is {@link HttpServerErrorException} with Internal Server Error - * status code in response.
- * NOTICE: This behaviour will be changed after REST layer response codes regulation - * - * @param fieldName name of the field to override - * @param incorrectValue incorrect value used instead of mock value + * Check unique constraint for name field while adding {@link Customer} */ - private void addWithIncorrectField(String fieldName, T incorrectValue) { - try { - Customer mockCustomer = getMockCustomer(); - setField(mockCustomer, fieldName, incorrectValue); - getResponseEntityFromPostRequest(mockCustomer); - } catch (IllegalAccessException | NoSuchFieldException e) { - fail(e.toString()); - } catch (HttpServerErrorException e) { - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, e.getStatusCode()); - } + @Test + public void checkUniqueConstraintForLogin_whenCustomerRequestStageAdd() { + addWithIncorrectField("login", getCreatedCustomer().getLogin()); + } + + /** + * Check unique constraint for email field while adding {@link Customer} + */ + @Test + public void checkUniqueConstraintForEmail_whenCustomerRequestStageAdd() { + addWithIncorrectField("email", getCreatedCustomer().getEmail()); + } + + /** + * Check not blank constraint for login while adding {@link Customer} + */ + @Test + public void checkNotBlankConstraintForLogin_whenCustomerRequestStageAdd() { + addWithIncorrectField("login", null); + addWithIncorrectField("login", ""); + addWithIncorrectField("login", " "); + addWithIncorrectField("login", " "); + addWithIncorrectField("login", "\t"); + addWithIncorrectField("login", "\n"); + } + + /** + * Check not blank constraint for email while adding {@link Customer} + */ + @Test + public void checkNotBlankConstraintForEmail_whenCustomerRequestStageAdd() { + addWithIncorrectField("email", null); + addWithIncorrectField("email", ""); + addWithIncorrectField("email", " "); + addWithIncorrectField("email", " "); + addWithIncorrectField("email", "\t"); + addWithIncorrectField("email", "\n"); + } + + /** + * Check not blank constraint for password while adding {@link Customer} + */ + @Test + public void checkNotBlankConstraintForPassword_whenCustomerRequestStageAdd() { + addWithIncorrectField("password", null); + addWithIncorrectField("password", ""); + addWithIncorrectField("password", " "); + addWithIncorrectField("password", " "); + addWithIncorrectField("password", "\t"); + addWithIncorrectField("password", "\n"); } /** @@ -442,4 +407,17 @@ private ResponseEntity getResponseEntityFromPostRequest(Customer custo Customer.class ); } + + /** + * Utility method for checking of some constraints during entity addition, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link io.khasang.ba.controller.utility.RestRequests#addEntityWithIncorrectField(Class, String, Object, HttpStatus)}. + * + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field + */ + private void addWithIncorrectField(String fieldName, V incorrectValue) { + addEntityWithIncorrectField(Customer.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); + } } From cae6251a16c935d867f8c9bde880425267b80879 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 11:20:58 +0300 Subject: [PATCH 10/28] feature/ba-0054: Fixed name of the method CustomerRequestStageNameControllerIntegrationTest#checkNotBlankConstraintForName_whenCustomerRequestStageUpdate, added some comments --- ...CustomerRequestStageNameControllerIntegrationTest.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageNameControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageNameControllerIntegrationTest.java index 068000f..8f9d8cf 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageNameControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerRequestStageNameControllerIntegrationTest.java @@ -125,6 +125,8 @@ public void checkCustomerRequestStageNameDelete() { HttpStatus.NOT_FOUND)); } + // Addition constraints + /** * Check unique constraint for name field while adding {@link CustomerRequestStageName} */ @@ -146,6 +148,8 @@ public void checkNotBlankConstraintForName_whenCustomerRequestStageAdd() { addWithIncorrectField("name", "\n"); } + // Update constraints + /** * Check unique constraint for name while updating {@link CustomerRequestStageName} */ @@ -158,7 +162,7 @@ public void checkUniqueConstraintForName_whenCustomerRequestStageUpdate() { * Check not blank constraint for name while updating {@link CustomerRequestStageName} */ @Test - public void checkNotBlankNameConstraintForName_whenCustomerRequestStageUpdate() { + public void checkNotBlankConstraintForName_whenCustomerRequestStageUpdate() { updateWithIncorrectField("name", null); updateWithIncorrectField("name", ""); updateWithIncorrectField("name", " "); @@ -167,6 +171,8 @@ public void checkNotBlankNameConstraintForName_whenCustomerRequestStageUpdate() updateWithIncorrectField("name", "\n"); } + // Utility methods + /** * Create mock {@link CustomerRequestStageName} instance, and add (i.e. POST) it to a REST resource * From 4512d13701316407d900bc7c4b2fcacff00989fd Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 11:29:22 +0300 Subject: [PATCH 11/28] feature/ba-0100: Modified CustomerControllerIntegrationTest#checkGetAllCustomers, added ParametrizedTypeReference> into RestRequests#typeReferencesMap --- .../CustomerControllerIntegrationTest.java | 47 +++++++++---------- .../ba/controller/utility/RestRequests.java | 2 + 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index 3830b05..3a85aae 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -3,14 +3,12 @@ import io.khasang.ba.entity.Customer; import io.khasang.ba.entity.CustomerInformation; import org.junit.Test; -import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; import java.lang.reflect.Field; import java.time.LocalDate; -import java.util.ArrayList; import java.util.List; import java.util.UUID; @@ -74,35 +72,36 @@ public void checkAddCustomer() { } /** - * Checks sequential addition of certain amount of customers addition and getting. Amount is set in - * {@link #TEST_ENTITIES_COUNT} constant + * Check {@link CustomerController#getAllCustomers()} method, i.e. HTTP method GET, used to + * get a list of {@link Customer} entities from REST resource + * entities.
+ *

First of all, continuous addition of {@link Customer} entities with amount equal to + * {@link io.khasang.ba.controller.utility.RestRequests#TEST_ENTITIES_AMOUNT} is performed. + * Secondly, top TEST_ENTITIES_AMOUNT of entities, obtained from response body, received from REST-resource, placed at + * {@link io.khasang.ba.controller.utility.RestRequests#GET_ALL_PATH}), compared with list of + * previously added entities. + *

*/ @Test public void checkGetAllCustomers() { - List createdCustomers = new ArrayList<>(TEST_ENTITIES_COUNT); - for (int i = 0; i < TEST_ENTITIES_COUNT; i++) { - createdCustomers.add(getCreatedCustomer()); - } - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity> responseEntity = restTemplate.exchange( - ROOT + GET_ALL, - HttpMethod.GET, - null, - new ParameterizedTypeReference>() { - } - ); - List allReceivedCustomers = responseEntity.getBody(); + // Create list of entities + List createdCustomersList = + getCreatedEntitiesList( + Customer.class, + TEST_ENTITIES_AMOUNT, + HttpStatus.CREATED); - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - assertNotNull(allReceivedCustomers); - assertFalse(allReceivedCustomers.isEmpty()); + // Receive all entities from REST + List allCustomers = + getAllEntitiesList(Customer.class, HttpStatus.OK); + // Check last TEST_ENTITIES_AMOUNT and assert for equality List receivedCustomersSubList = - allReceivedCustomers.subList(allReceivedCustomers.size() - TEST_ENTITIES_COUNT, allReceivedCustomers.size()); - for (int i = 0; i < TEST_ENTITIES_COUNT; i++) { - assertEquals(createdCustomers.get(i), receivedCustomersSubList.get(i)); - } + allCustomers.subList(allCustomers.size() - TEST_ENTITIES_AMOUNT, + allCustomers.size()); + + assertEquals(createdCustomersList, receivedCustomersSubList); } /** diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java index 802bc1d..36189d0 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java @@ -66,6 +66,8 @@ public final class RestRequests { */ public static final Map, ParameterizedTypeReference> typeReferencesMap = new HashMap, ParameterizedTypeReference>() {{ + put(Customer.class, new ParameterizedTypeReference>() { + }); put(CustomerRequestStage.class, new ParameterizedTypeReference>() { }); put(CustomerRequestStageName.class, new ParameterizedTypeReference>() { From 2f54d0e64b122d868e073424200193470eee396a Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 11:48:27 +0300 Subject: [PATCH 12/28] feature/ba-0100: Modified CustomerControllerIntegrationTest#checkUpdateCustomer --- .../CustomerControllerIntegrationTest.java | 41 +++++++++++++++---- 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index 3a85aae..5e5d958 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -12,6 +12,7 @@ import java.util.List; import java.util.UUID; +import static io.khasang.ba.controller.utility.MockFactory.getChangedMockCustomer; import static io.khasang.ba.controller.utility.MockFactory.getMockCustomer; import static io.khasang.ba.controller.utility.RestRequests.*; import static org.junit.Assert.*; @@ -105,17 +106,24 @@ public void checkGetAllCustomers() { } /** - * Check of customer entity update via PUT request + * Check {@link CustomerController#updateCustomer(Customer)}, i.e. HTTP method + * PUT, used to update an {@link Customer} entity on REST resource */ @Test public void checkUpdateCustomer() { - Customer customer = getChangedCustomer(getCreatedCustomer()); - putCustomerToUpdate(customer); - Customer updatedCustomer = getCustomerById(customer.getId()); - assertNotNull(updatedCustomer); - assertNotNull(updatedCustomer.getId()); - assertEquals(customer, updatedCustomer); + // POST, then UPDATE in REST + Customer updatedCustomer = getUpdatedCustomer(); + + //Get it from REST, check id and assertEquals + Customer receivedCustomer = + getEntityById( + updatedCustomer.getId(), + Customer.class, + HttpStatus.OK); + + assertNotNull(receivedCustomer.getId()); + assertEquals(updatedCustomer, receivedCustomer); } /** @@ -407,6 +415,25 @@ private ResponseEntity getResponseEntityFromPostRequest(Customer custo ); } + /** + * Update existing {@link Customer} entity at REST resource. Firstly, add new mock entity and then + * PUT updated entity to REST resource + * + * @return updated at REST resource instance of entity + */ + private Customer getUpdatedCustomer() { + Customer createdCustomer = getCreatedCustomer(); + + Customer updatedCustomer = + getResponseFromEntityUpdateRequest( + getChangedMockCustomer(createdCustomer), + HttpStatus.OK); + + assertEquals(createdCustomer.getId(), updatedCustomer.getId()); + + return updatedCustomer; + } + /** * Utility method for checking of some constraints during entity addition, which has simpler signature * with reduced number of parameters. It could be used instead of From bef68ed18788bfc60e72dc3fd2c697d98971a1ba Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 11:59:35 +0300 Subject: [PATCH 13/28] feature/ba-0100: Removed unnecessary CustomerControllerIntegrationTest#getResponseEntityFromPostRequest --- .../CustomerControllerIntegrationTest.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index 5e5d958..e4e547d 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -395,26 +395,6 @@ private Customer getCreatedCustomer() { return createdCustomer; } - /** - * Add customer entity via POST request - * - * @param customer {@link Customer} instance, which should be added via POST request - * @return {@link ResponseEntity} containing response data - */ - private ResponseEntity getResponseEntityFromPostRequest(Customer customer) { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - HttpEntity httpEntity = new HttpEntity<>(customer, httpHeaders); - - RestTemplate restTemplate = new RestTemplate(); - return restTemplate.exchange( - ROOT + ADD, - HttpMethod.POST, - httpEntity, - Customer.class - ); - } - /** * Update existing {@link Customer} entity at REST resource. Firstly, add new mock entity and then * PUT updated entity to REST resource From 9fe94badec04f96a3253b7bb838f9b9d70fad7d4 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 12:52:09 +0300 Subject: [PATCH 14/28] feature/ba-0100: Removed unnecessary CustomerControllerIntegrationTest#getCustomerById --- .../CustomerControllerIntegrationTest.java | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index e4e547d..e0c74f2 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -311,26 +311,6 @@ private void setField(Customer customer, String fieldName, T fieldValue) declaredField.setAccessible(false); } - /** - * Method for customer getting by id - * - * @param id Id in table of customers - * @return Found {@link Customer} instance - */ - private Customer getCustomerById(Long id) { - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + GET_BY_ID, - HttpMethod.GET, - null, - Customer.class, - id - ); - Customer receivedCustomer = responseEntity.getBody(); - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - return receivedCustomer; - } - /** * Put customer for update * From de25e34e75972317a770f0831b9bf552f88caaf0 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 14:07:04 +0300 Subject: [PATCH 15/28] feature/ba-0100: 1) In the CustomerControllerIntegrationTest added methods for constraint checks during updating an entity. 2) Added overloaded version for RestRequests#updateEntityWithIncorrectField method. --- .../CustomerControllerIntegrationTest.java | 168 +++++++++--------- .../ba/controller/utility/RestRequests.java | 27 +++ 2 files changed, 107 insertions(+), 88 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index e0c74f2..489940b 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -4,7 +4,6 @@ import io.khasang.ba.entity.CustomerInformation; import org.junit.Test; import org.springframework.http.*; -import org.springframework.web.client.HttpServerErrorException; import org.springframework.web.client.RestTemplate; import java.lang.reflect.Field; @@ -126,75 +125,6 @@ public void checkUpdateCustomer() { assertEquals(updatedCustomer, receivedCustomer); } - /** - * Check customer's login update constraint during updating process - */ - @Test(expected = HttpServerErrorException.class) - public void checkLoginUpdate() { - Customer customer = getCreatedCustomer(); - customer.setLogin(TEST_CUSTOMER_LOGIN_PREFIX + UUID.randomUUID().toString()); - putCustomerToUpdate(customer); - } - - /** - * Check unique constraint for customer's e-mail during updating process - */ - @Test(expected = HttpServerErrorException.class) - public void checkUpdateEmailUniqueConstraint() { - Customer customer1 = getCreatedCustomer(); - Customer customer2 = getCreatedCustomer(); - customer2.setEmail(customer1.getEmail()); - putCustomerToUpdate(customer2); - } - - /** - * Check NotBlank(+ NotNull + NotEmpty) constraint for customer's login during updating process - */ - @Test - public void checkUpdateWithBlankLogin() { - - //NotNull + NotEmpty - updateWithIncorrectField("login", null); - updateWithIncorrectField("login", ""); - - //Check NotBlank (whitespaces and some other characters) - updateWithIncorrectField("login", " "); - updateWithIncorrectField("login", "\t"); - updateWithIncorrectField("login", "\n"); - } - - /** - * Check NotBlank(+ NotNull + NotEmpty) constraint for customer's email during updating process - */ - @Test - public void checkUpdateWithBlankEmail() { - - //NotNull + NotEmpty - updateWithIncorrectField("email", null); - updateWithIncorrectField("email", ""); - - //Check NotBlank (whitespaces and some other characters) - updateWithIncorrectField("email", " "); - updateWithIncorrectField("email", "\t"); - updateWithIncorrectField("email", "\n"); - } - - /** - * Check NotBlank(+ NotNull + NotEmpty) constraint for customer's password during updating process - */ - @Test - public void checkUpdateWithBlankPassword() { - - //NotNull + NotEmpty - updateWithIncorrectField("password", null); - updateWithIncorrectField("password", ""); - - //Check NotBlank (whitespaces and some other characters) - updateWithIncorrectField("password", " "); - updateWithIncorrectField("password", "\t"); - updateWithIncorrectField("password", "\n"); - } - /** * Check {@link CustomerController#deleteCustomer(long)}, i.e. HTTP method * DELETE, used to delete an {@link Customer} entity on REST resource @@ -271,28 +201,77 @@ public void checkNotBlankConstraintForPassword_whenCustomerRequestStageAdd() { addWithIncorrectField("password", "\n"); } + // Update constraints + /** - * Utility method to check Customer entity updating with incorrect field (overriding mock value). - * Field is changed by Java reflections mechanisms.
- * Method checks that thrown exception is {@link HttpServerErrorException} with Internal Server Error - * status code in response.
- * NOTICE: This behaviour will be changed after REST layer response codes regulation - * - * @param fieldName name of the field to override - * @param incorrectValue incorrect value used instead of mock value + * Check immutable constraint for login while updating {@link Customer} */ - private void updateWithIncorrectField(String fieldName, T incorrectValue) { - try { - Customer customer = getChangedCustomer(getCreatedCustomer()); - setField(customer, fieldName, incorrectValue); - putCustomerToUpdate(customer); - } catch (IllegalAccessException | NoSuchFieldException e) { - fail(e.toString()); - } catch (HttpServerErrorException e) { - assertEquals(HttpStatus.INTERNAL_SERVER_ERROR, e.getStatusCode()); - } + @Test + public void checkImmutableConstraintForLogin_whenCustomerRequestStageUpdate() { + updateEntityWithIncorrectField( + getCreatedCustomer(), + "login", + UUID.randomUUID().toString(), + HttpStatus.INTERNAL_SERVER_ERROR); } + /** + * Check unique constraint for login while updating {@link Customer} + */ + @Test + public void checkUniqueConstraintForLogin_whenCustomerRequestStageUpdate() { + updateWithIncorrectField("login", getCreatedCustomer().getLogin()); + } + + /** + * Check unique constraint for email while updating {@link Customer} + */ + @Test + public void checkUniqueConstraintForEmail_whenCustomerRequestStageUpdate() { + updateWithIncorrectField("email", getCreatedCustomer().getEmail()); + } + + /** + * Check not blank constraint for login while updating {@link Customer} + */ + @Test + public void checkNotBlankConstraintForLogin_whenCustomerRequestStageUpdate() { + updateWithIncorrectField("login", null); + updateWithIncorrectField("login", ""); + updateWithIncorrectField("login", " "); + updateWithIncorrectField("login", " "); + updateWithIncorrectField("login", "\t"); + updateWithIncorrectField("login", "\n"); + } + + /** + * Check not blank constraint for email while updating {@link Customer} + */ + @Test + public void checkNotBlankConstraintForEmail_whenCustomerRequestStageUpdate() { + updateWithIncorrectField("email", null); + updateWithIncorrectField("email", ""); + updateWithIncorrectField("email", " "); + updateWithIncorrectField("email", " "); + updateWithIncorrectField("email", "\t"); + updateWithIncorrectField("email", "\n"); + } + + /** + * Check not blank constraint for password while updating {@link Customer} + */ + @Test + public void checkNotBlankConstraintForPassword_whenCustomerRequestStageUpdate() { + updateWithIncorrectField("password", null); + updateWithIncorrectField("password", ""); + updateWithIncorrectField("password", " "); + updateWithIncorrectField("password", " "); + updateWithIncorrectField("password", "\t"); + updateWithIncorrectField("password", "\n"); + } + + // Utility methods + /** * Utility method to set a Customer's field via reflection mechanism * @@ -406,4 +385,17 @@ private Customer getUpdatedCustomer() { private void addWithIncorrectField(String fieldName, V incorrectValue) { addEntityWithIncorrectField(Customer.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); } + + /** + * Utility method for checking of some constraints during entity update, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link io.khasang.ba.controller.utility.RestRequests#updateEntityWithIncorrectField(Class, String, Object, HttpStatus)}. + * + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field + */ + private void updateWithIncorrectField(String fieldName, V incorrectValue) { + updateEntityWithIncorrectField(Customer.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); + } } diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java index 36189d0..b8bb2eb 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java @@ -280,6 +280,33 @@ public static void updateEntityWithIncorrectField(Class entityClass, S expectedErrorStatusCode); } + /** + *

Check update of an entity with incorrect field (with incorrect value or with violating such constraints, as NotNull, Unique) + * at corresponding REST resource, which path is detected by class by means of {@link #restRootsMap}. + * Field value is set via java reflection mechanisms.

+ *

Difference with {@link #updateEntityWithIncorrectField(Class, String, Object, HttpStatus)} consist in that this method + * performs update for properly created entity from REST resource. + *

In a case of absence of {@link HttpClientErrorException} or {@link HttpServerErrorException}, method fails with assertion error + * NOTICE: This behaviour will be changed after REST layer response codes regulation

+ * + * @param entity an entity class + * @param fieldName a field, which should be changed + * @param incorrectValue incorrect value for changing field + * @param expectedErrorStatusCode expected HTTP status code error + * @param type of the entity both of request and response + * @param type of the field + */ + public static void updateEntityWithIncorrectField(T entity, String fieldName, V incorrectValue, + HttpStatus expectedErrorStatusCode) { + sendEntityWithIncorrectField( + entity, + fieldName, + incorrectValue, + restRootsMap.get(entity.getClass()) + UPDATE_PATH, + HttpMethod.PUT, + expectedErrorStatusCode); + } + /** * Check sending of an entity with incorrect field (with incorrect value or with violating such constraints, as NotNull, Unique) * to a given REST resource. Field is changed via java reflection mechanisms.
From 4b3cd826da01948e0138cb5cb7d05cbe507062f1 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 14:09:45 +0300 Subject: [PATCH 16/28] feature/ba-0100: Removed unnecessary fields and methods in the CustomerControllerIntegrationTest. --- .../CustomerControllerIntegrationTest.java | 90 +------------------ 1 file changed, 1 insertion(+), 89 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java index 489940b..fe9f9b4 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CustomerControllerIntegrationTest.java @@ -1,13 +1,9 @@ package io.khasang.ba.controller; import io.khasang.ba.entity.Customer; -import io.khasang.ba.entity.CustomerInformation; import org.junit.Test; -import org.springframework.http.*; -import org.springframework.web.client.RestTemplate; +import org.springframework.http.HttpStatus; -import java.lang.reflect.Field; -import java.time.LocalDate; import java.util.List; import java.util.UUID; @@ -20,25 +16,6 @@ * Integration test for Customer REST layer */ public class CustomerControllerIntegrationTest { - //Mock data configuration - private static final String TEST_CUSTOMER_LOGIN_PREFIX = "TEST_CUSTOMER_"; - private static final String TEST_CUSTOMER_RAW_PASSWORD = "123tEsT#"; - private static final String TEST_CUSTOMER_EMAIL_SUFFIX = "@ba.khasang.io"; - private static final String TEST_CUSTOMER_FULL_NAME = "Ivan Petrov"; - private static final LocalDate TEST_CUSTOMER_BIRTHDATE = LocalDate.of(1986, 8, 26); - private static final String TEST_CUSTOMER_COUNTRY = "Russia"; - private static final String TEST_CUSTOMER_CITY = "Saint Petersburg"; - private static final String TEST_CUSTOMER_ABOUT = "Another one mock test customer"; - - //Amount of test entities - private static final int TEST_ENTITIES_COUNT = 30; - - private static final String ROOT = "http://localhost:8080/customer"; - private static final String ADD = "/add"; - private static final String GET_BY_ID = "/get/{id}"; - private static final String GET_ALL = "/get/all"; - private static final String UPDATE = "/update"; - private static final String DELETE_BY_ID = "/delete/{id}"; /** * Check, that {@link CustomerController#getCustomerById(long)} gives NOT FOUND HTTP response @@ -272,71 +249,6 @@ public void checkNotBlankConstraintForPassword_whenCustomerRequestStageUpdate() // Utility methods - /** - * Utility method to set a Customer's field via reflection mechanism - * - * @param customer Customer instance to set field for - * @param fieldName name of field (eg. "login" or "email") - * @param fieldValue field value - * @param type parameter of field - * @throws NoSuchFieldException if field with specified fieldName not found - * @throws IllegalAccessException in case of access errors - */ - private void setField(Customer customer, String fieldName, T fieldValue) - throws NoSuchFieldException, IllegalAccessException { - Field declaredField = Customer.class.getDeclaredField(fieldName); - declaredField.setAccessible(true); - declaredField.set(customer, fieldValue); - declaredField.setAccessible(false); - } - - /** - * Put customer for update - * - * @param customer Customer, which should be updated on service - */ - private void putCustomerToUpdate(Customer customer) { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - HttpEntity httpEntity = new HttpEntity<>(customer, httpHeaders); - - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + UPDATE, - HttpMethod.PUT, - httpEntity, - Customer.class - ); - - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - assertNotNull(responseEntity.getBody()); - } - - /** - * Change users field for further update - * - * @param oldCustomer customer instance which updated {@link Customer} - * @return updated customer - */ - private Customer getChangedCustomer(Customer oldCustomer) { - Customer newCustomer = new Customer(); - CustomerInformation customerInformation = new CustomerInformation(); - - newCustomer.setId(oldCustomer.getId()); - newCustomer.setLogin(oldCustomer.getLogin()); - newCustomer.setPassword("new_password"); - newCustomer.setEmail(UUID.randomUUID().toString() + "@newmail.com"); - newCustomer.setCustomerInformation(customerInformation); - - customerInformation.setFullName("New Full Name"); - customerInformation.setBirthDate(LocalDate.of(1990, 10, 15)); - customerInformation.setCountry("USA"); - customerInformation.setCity("New York"); - customerInformation.setAbout("new_about"); - - return newCustomer; - } - /** * Create mock {@link Customer} instance, and add (i.e. POST) it to a REST resource * From 01ce30235d11f9d48f6417d1e3ab108691f6ed40 Mon Sep 17 00:00:00 2001 From: Ilya Shishkov Date: Thu, 23 May 2019 20:49:45 +0300 Subject: [PATCH 17/28] enhancement/ba-0103: 1) An OperatorControllerIntegrationTest is migrated into the RestRequests and MockFactory/ 2) An Operator entity migrated to Lombok (including embeddable) 3) OperatorController modified as RestController (including status codes) 4) MockFactory#getMockCustomerRequestStage fixed - changed status code to CREATED fot list of Operator entities --- .../OperatorControllerIntegrationTest.java | 546 +++++++----------- .../ba/controller/utility/MockFactory.java | 46 +- .../ba/controller/OperatorController.java | 32 +- .../java/io/khasang/ba/entity/Operator.java | 80 +-- .../ba/entity/OperatorInformation.java | 61 +- 5 files changed, 259 insertions(+), 506 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/OperatorControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/OperatorControllerIntegrationTest.java index e5b53d5..3f7305c 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/OperatorControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/OperatorControllerIntegrationTest.java @@ -1,463 +1,313 @@ package io.khasang.ba.controller; import io.khasang.ba.entity.Operator; -import io.khasang.ba.entity.OperatorInformation; import org.junit.Test; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; -import org.springframework.web.client.HttpServerErrorException; -import org.springframework.web.client.RestTemplate; - -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.ArrayList; +import org.springframework.http.HttpStatus; + import java.util.List; import java.util.UUID; +import static io.khasang.ba.controller.utility.MockFactory.getChangedMockOperator; +import static io.khasang.ba.controller.utility.MockFactory.getMockOperator; +import static io.khasang.ba.controller.utility.RestRequests.*; import static org.junit.Assert.*; /** * Integration test for Operator REST layer */ public class OperatorControllerIntegrationTest { - //Mock data configuration - private static final String TEST_OPERATOR_LOGIN_PREFIX = "TEST_OPERATOR_"; - private static final String TEST_OPERATOR_RAW_PASSWORD = "123tEsT#"; - private static final String TEST_OPERATOR_EMAIL_SUFFIX = "@ba.khasang.io"; - private static final String TEST_OPERATOR_FULL_NAME = "Ivan Petrov"; - private static final LocalDate TEST_OPERATOR_BIRTHDATE = LocalDate.of(1986, 8, 26); - private static final String TEST_OPERATOR_COUNTRY = "Russia"; - private static final String TEST_OPERATOR_CITY = "Saint Petersburg"; - private static final String TEST_OPERATOR_ABOUT = "Another one mock test operator"; - - //Amount of test entities - private static final int TEST_ENTITIES_COUNT = 30; - - private static final String ROOT = "http://localhost:8080/operator"; - private static final String ADD = "/add"; - private static final String GET_BY_ID = "/get/{id}"; - private static final String GET_ALL = "/get/all"; - private static final String UPDATE = "/update"; - private static final String DELETE_BY_ID = "/delete/{id}"; /** - * Check operator addition + * Check, that {@link OperatorController#getOperatorById(long)} gives NOT FOUND HTTP response + * in the case of attempt to get nonexistent entity, i.e. entity with nonexistent Id. */ @Test - public void checkAddOperator() { - Operator createdOperator = getCreatedOperator(); - Operator receivedOperator = getOperatorById(createdOperator.getId()); - assertNotNull(receivedOperator); - assertEquals(createdOperator, receivedOperator); + public void checkGetNonExistentOperator() { + getEntityById(Long.MAX_VALUE, Operator.class, HttpStatus.NOT_FOUND); } /** - * Check unique login constraint for operator's login during addition process + * Check both {@link OperatorController#getOperatorById(long)} and + * {@link OperatorController#addOperator(Operator)} methods, + * i.e. HTTP methods GET and POST, providing possibilities to get an {@link Operator} entity + * from REST resource and to add it to the resource. */ - @Test(expected = HttpServerErrorException.class) - public void checkAddLoginUniqueConstraint() { - Operator operator = getCreatedOperator(); - Operator operatorWithSameLogin = getMockOperator(); - operatorWithSameLogin.setLogin(operator.getLogin()); - getResponseEntityFromPostRequest(operatorWithSameLogin); - } + @Test + public void checkAddOperator() { - /** - * Check unique constraint for operator's e-mail during addition process - */ - @Test(expected = HttpServerErrorException.class) - public void checkAddEmailUniqueConstraint() { - Operator operator = getCreatedOperator(); - Operator operatorWithSameEmail = getMockOperator(); - operatorWithSameEmail.setEmail(operator.getEmail()); - getResponseEntityFromPostRequest(operatorWithSameEmail); - } + //POST to REST + Operator createdOperator = getCreatedOperator(); - /** - * Check not-null constraint for operator's login during addition process - */ - @Test(expected = HttpServerErrorException.class) - public void checkAddWithNullLogin() { - Operator operatorWithNullLogin = getMockOperator(); - operatorWithNullLogin.setLogin(null); - getResponseEntityFromPostRequest(operatorWithNullLogin); - } + // GET from REST + Operator receivedOperator = + getEntityById( + createdOperator.getId(), + Operator.class, + HttpStatus.OK); - /** - * Check not-empty constraint for operator's login during addition process - */ - @Test(expected = HttpServerErrorException.class) - public void checkAddWithEmptyLogin() { - Operator operatorWithEmptyLogin = getMockOperator(); - operatorWithEmptyLogin.setLogin(""); - getResponseEntityFromPostRequest(operatorWithEmptyLogin); + assertEquals(createdOperator, receivedOperator); } /** - * Check not-null constraint for operator's email during addition process + * Check {@link OperatorController#getAllOperators()} method, i.e. HTTP method GET, used to + * get a list of {@link Operator} entities from REST resource + * entities.
+ *

First of all, continuous addition of {@link Operator} entities with amount equal to + * {@link io.khasang.ba.controller.utility.RestRequests#TEST_ENTITIES_AMOUNT} is performed. + * Secondly, top TEST_ENTITIES_AMOUNT of entities, obtained from response body, received from REST-resource, placed at + * {@link io.khasang.ba.controller.utility.RestRequests#GET_ALL_PATH}), compared with list of + * previously added entities. + *

*/ - @Test(expected = HttpServerErrorException.class) - public void checkAddWithNullEmail() { - Operator operatorWithNullEmail = getMockOperator(); - operatorWithNullEmail.setEmail(null); - getResponseEntityFromPostRequest(operatorWithNullEmail); - } + @Test + public void checkGetAllOperators() { - /** - * Check not-empty constraint for operator's email during addition process - */ - @Test(expected = HttpServerErrorException.class) - public void checkAddWithEmptyEmail() { - Operator operatorWithEmptyEmail = getMockOperator(); - operatorWithEmptyEmail.setEmail(""); - getResponseEntityFromPostRequest(operatorWithEmptyEmail); - } + // Create list of entities + List createdOperatorsList = + getCreatedEntitiesList( + Operator.class, + TEST_ENTITIES_AMOUNT, + HttpStatus.CREATED); - /** - * Check not-null constraint for operator's password during addition process - */ - @Test(expected = HttpServerErrorException.class) - public void checkAddWithNullPassword() { - Operator operatorWithNullPassword = getMockOperator(); - operatorWithNullPassword.setPassword(null); - getResponseEntityFromPostRequest(operatorWithNullPassword); - } + // Receive all entities from REST + List allOperators = + getAllEntitiesList(Operator.class, HttpStatus.OK); - /** - * Check not-empty constraint for operator's password during addition process - */ - @Test(expected = HttpServerErrorException.class) - public void checkAddWithEmptyPassword() { - Operator operatorWithEmptyPassword = getMockOperator(); - operatorWithEmptyPassword.setPassword(""); - getResponseEntityFromPostRequest(operatorWithEmptyPassword); + // Check last TEST_ENTITIES_AMOUNT and assert for equality + List receivedOperatorsSubList = + allOperators.subList(allOperators.size() - TEST_ENTITIES_AMOUNT, + allOperators.size()); + + assertEquals(createdOperatorsList, receivedOperatorsSubList); } /** - * Checks sequential addition of certain amount of operators addition and getting. Amount is set in - * {@link #TEST_ENTITIES_COUNT} constant + * Check {@link OperatorController#updateOperator(Operator)}, i.e. HTTP method + * PUT, used to update an {@link Operator} entity on REST resource */ @Test - public void checkGetAllOperators() { - List createdOperators = new ArrayList<>(TEST_ENTITIES_COUNT); - for (int i = 0; i < TEST_ENTITIES_COUNT; i++) { - createdOperators.add(getCreatedOperator()); - } - - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity> responseEntity = restTemplate.exchange( - ROOT + GET_ALL, - HttpMethod.GET, - null, - new ParameterizedTypeReference>() { - } - ); - List allReceivedOperators = responseEntity.getBody(); - - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - assertNotNull(allReceivedOperators); - assertFalse(allReceivedOperators.isEmpty()); + public void checkUpdateOperator() { - List receivedOperatorsSubList = - allReceivedOperators.subList(allReceivedOperators.size() - TEST_ENTITIES_COUNT, allReceivedOperators.size()); - for (int i = 0; i < TEST_ENTITIES_COUNT; i++) { - assertEquals(createdOperators.get(i), receivedOperatorsSubList.get(i)); - } + // POST, then UPDATE in REST + Operator updatedOperator = getUpdatedOperator(); + + //Get it from REST, check id and assertEquals + Operator receivedOperator = + getEntityById( + updatedOperator.getId(), + Operator.class, + HttpStatus.OK); + + assertNotNull(receivedOperator.getId()); + assertEquals(updatedOperator, receivedOperator); } /** - * Check of operator entity update via PUT request + * Check {@link OperatorController#deleteOperator(long)}, i.e. HTTP method + * DELETE, used to delete an {@link Operator} entity on REST resource */ @Test - public void checkUpdateOperator() { - Operator operator = getChangedOperator(getCreatedOperator()); - putOperatorToUpdate(operator); + public void checkOperatorDelete() { + Operator createdOperator = getCreatedOperator(); - Operator updatedOperator = getOperatorById(operator.getId()); - assertNotNull(updatedOperator); - assertNotNull(updatedOperator.getId()); - assertEquals(operator, updatedOperator); + getResponseFromEntityDeleteRequest( + createdOperator.getId(), + Operator.class, + HttpStatus.NO_CONTENT); + + assertNull(getEntityById( + createdOperator.getId(), + Operator.class, + HttpStatus.NOT_FOUND)); } + //Addition constraints + /** - * Check operator's login update constraint during updating process + * Check unique constraint for name field while adding {@link Operator} */ - @Test(expected = HttpServerErrorException.class) - public void checkLoginUpdate() { - Operator operator = getCreatedOperator(); - operator.setLogin(TEST_OPERATOR_LOGIN_PREFIX + UUID.randomUUID().toString()); - putOperatorToUpdate(operator); + @Test + public void checkUniqueConstraintForLogin_whenOperatorRequestStageAdd() { + addWithIncorrectField("login", getCreatedOperator().getLogin()); } /** - * Check unique constraint for operator's e-mail during updating process + * Check unique constraint for email field while adding {@link Operator} */ - @Test(expected = HttpServerErrorException.class) - public void checkUpdateEmailUniqueConstraint() { - Operator operator1 = getCreatedOperator(); - Operator operator2 = getCreatedOperator(); - operator2.setEmail(operator1.getEmail()); - putOperatorToUpdate(operator2); + @Test + public void checkUniqueConstraintForEmail_whenOperatorRequestStageAdd() { + addWithIncorrectField("email", getCreatedOperator().getEmail()); } /** - * Check not-null constraint for operator's email during updating process + * Check not blank constraint for login while adding {@link Operator} */ - @Test(expected = HttpServerErrorException.class) - public void checkUpdateWithNullEmail() { - Operator operator = getCreatedOperator(); - operator.setEmail(null); - putOperatorToUpdate(operator); + @Test + public void checkNotBlankConstraintForLogin_whenOperatorRequestStageAdd() { + addWithIncorrectField("login", null); + addWithIncorrectField("login", ""); + addWithIncorrectField("login", " "); + addWithIncorrectField("login", " "); + addWithIncorrectField("login", "\t"); + addWithIncorrectField("login", "\n"); } /** - * Check not-empty constraint for operator's email during updating process + * Check not blank constraint for email while adding {@link Operator} */ - @Test(expected = HttpServerErrorException.class) - public void checkUpdateWithEmptyEmail() { - Operator operator = getCreatedOperator(); - operator.setEmail(""); - putOperatorToUpdate(operator); + @Test + public void checkNotBlankConstraintForEmail_whenOperatorRequestStageAdd() { + addWithIncorrectField("email", null); + addWithIncorrectField("email", ""); + addWithIncorrectField("email", " "); + addWithIncorrectField("email", " "); + addWithIncorrectField("email", "\t"); + addWithIncorrectField("email", "\n"); } /** - * Check not-null constraint for operator's password during updating process + * Check not blank constraint for password while adding {@link Operator} */ - @Test(expected = HttpServerErrorException.class) - public void checkUpdateWithNullPassword() { - Operator operator = getCreatedOperator(); - operator.setPassword(null); - putOperatorToUpdate(operator); + @Test + public void checkNotBlankConstraintForPassword_whenOperatorRequestStageAdd() { + addWithIncorrectField("password", null); + addWithIncorrectField("password", ""); + addWithIncorrectField("password", " "); + addWithIncorrectField("password", " "); + addWithIncorrectField("password", "\t"); + addWithIncorrectField("password", "\n"); } + // Update constraints + /** - * Check not-empty constraint for operator's password during updating process + * Check immutable constraint for login while updating {@link Operator} */ - @Test(expected = HttpServerErrorException.class) - public void checkUpdateWithEmptyPassword() { - Operator operator = getCreatedOperator(); - operator.setPassword(""); - putOperatorToUpdate(operator); + @Test + public void checkImmutableConstraintForLogin_whenOperatorRequestStageUpdate() { + updateEntityWithIncorrectField( + getCreatedOperator(), + "login", + UUID.randomUUID().toString(), + HttpStatus.INTERNAL_SERVER_ERROR); } /** - * Check of operator deletion + * Check unique constraint for login while updating {@link Operator} */ @Test - public void checkOperatorDelete() { - Operator operator = getCreatedOperator(); - Operator deletedOperator = getDeletedOperator(operator.getId()); - assertEquals(operator, deletedOperator); - assertNull(getOperatorById(operator.getId())); + public void checkUniqueConstraintForLogin_whenOperatorRequestStageUpdate() { + updateWithIncorrectField("login", getCreatedOperator().getLogin()); } /** - * Utility method which deletes operator by id and retrieves operator entity from DELETE response body - * - * @param id Id of the operator which should be deleted - * @return Deleted operator + * Check unique constraint for email while updating {@link Operator} */ - private Operator getDeletedOperator(Long id) { - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + DELETE_BY_ID, - HttpMethod.DELETE, - null, - Operator.class, - id - ); - Operator deletedOperator = responseEntity.getBody(); - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - assertNotNull(deletedOperator); - return deletedOperator; + @Test + public void checkUniqueConstraintForEmail_whenOperatorRequestStageUpdate() { + updateWithIncorrectField("email", getCreatedOperator().getEmail()); } /** - * Method for operator getting by id - * - * @param id Id in table of operators - * @return Found {@link Operator} instance + * Check not blank constraint for login while updating {@link Operator} */ - private Operator getOperatorById(Long id) { - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + GET_BY_ID, - HttpMethod.GET, - null, - Operator.class, - id - ); - Operator receivedOperator = responseEntity.getBody(); - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - return receivedOperator; + @Test + public void checkNotBlankConstraintForLogin_whenOperatorRequestStageUpdate() { + updateWithIncorrectField("login", null); + updateWithIncorrectField("login", ""); + updateWithIncorrectField("login", " "); + updateWithIncorrectField("login", " "); + updateWithIncorrectField("login", "\t"); + updateWithIncorrectField("login", "\n"); } /** - * Put operator for update - * - * @param operator Operator, which should be updated on service + * Check not blank constraint for email while updating {@link Operator} */ - private void putOperatorToUpdate(Operator operator) { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - HttpEntity httpEntity = new HttpEntity<>(operator, httpHeaders); - - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + UPDATE, - HttpMethod.PUT, - httpEntity, - Operator.class - ); - - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - assertNotNull(responseEntity.getBody()); + @Test + public void checkNotBlankConstraintForEmail_whenOperatorRequestStageUpdate() { + updateWithIncorrectField("email", null); + updateWithIncorrectField("email", ""); + updateWithIncorrectField("email", " "); + updateWithIncorrectField("email", " "); + updateWithIncorrectField("email", "\t"); + updateWithIncorrectField("email", "\n"); } /** - * Change operators field for further update - * - * @param oldOperator operator instance which updated {@link Operator} - * @return updated operator + * Check not blank constraint for password while updating {@link Operator} */ - private Operator getChangedOperator(Operator oldOperator) { - OperatorBuilder operatorBuilder = new OperatorBuilder(); - Operator newOperator = operatorBuilder - .addLogin(oldOperator.getLogin()) - .addEmail(UUID.randomUUID().toString() + "@newmail.com") - .addPassword("new_password") - .addFullName("New Full Name") - .addBirthDate(LocalDate.of(1990, 10, 15)) - .addCountry("USA") - .addCity("New York") - .addAbout("new_about") - .build(); - newOperator.setId(oldOperator.getId()); - return newOperator; + @Test + public void checkNotBlankConstraintForPassword_whenOperatorRequestStageUpdate() { + updateWithIncorrectField("password", null); + updateWithIncorrectField("password", ""); + updateWithIncorrectField("password", " "); + updateWithIncorrectField("password", " "); + updateWithIncorrectField("password", "\t"); + updateWithIncorrectField("password", "\n"); } + // Utility methods + /** - * Get created test operator entity from POST response during operator creation procedure. Instead of creating {@link Operator} - * instance by constructor, this method returns instance from response, thus created operator contains table identifier + * Create mock {@link Operator} instance, and add (i.e. POST) it to a REST resource * - * @return Instance of {@link Operator} with generated identifier + * @return added to REST resource entity */ private Operator getCreatedOperator() { Operator operator = getMockOperator(); - LocalDateTime timeBeforeCreation = LocalDateTime.now(); - ResponseEntity responseEntity = getResponseEntityFromPostRequest(operator); - Operator createdOperator = responseEntity.getBody(); - LocalDateTime timeAfterCreation = LocalDateTime.now(); + Operator createdOperator = + getResponseFromEntityAddRequest(operator, HttpStatus.CREATED); - assertEquals(HttpStatus.OK, responseEntity.getStatusCode()); - assertNotNull(createdOperator); assertNotNull(createdOperator.getId()); assertEquals(operator, createdOperator); - assertEquals(-1, timeBeforeCreation.compareTo(createdOperator.getRegistrationTimestamp())); - assertEquals(1, timeAfterCreation.compareTo(createdOperator.getRegistrationTimestamp())); + return createdOperator; } /** - * Build mock {@link Operator} instance vie {@link OperatorBuilder} + * Update existing {@link Operator} entity at REST resource. Firstly, add new mock entity and then + * PUT updated entity to REST resource * - * @return prefilled mock operator instance + * @return updated at REST resource instance of entity */ - private Operator getMockOperator() { - OperatorBuilder operatorBuilder = new OperatorBuilder(); - return operatorBuilder - .addLogin(TEST_OPERATOR_LOGIN_PREFIX + UUID.randomUUID().toString()) - .addEmail(UUID.randomUUID().toString() + TEST_OPERATOR_EMAIL_SUFFIX) - .addAbout(TEST_OPERATOR_ABOUT) - .addCity(TEST_OPERATOR_CITY) - .addFullName(TEST_OPERATOR_FULL_NAME) - .addPassword(TEST_OPERATOR_RAW_PASSWORD) - .addBirthDate(TEST_OPERATOR_BIRTHDATE) - .addCountry(TEST_OPERATOR_COUNTRY) - .build(); + private Operator getUpdatedOperator() { + Operator createdOperator = getCreatedOperator(); + + Operator updatedOperator = + getResponseFromEntityUpdateRequest( + getChangedMockOperator(createdOperator), + HttpStatus.OK); + + assertEquals(createdOperator.getId(), updatedOperator.getId()); + + return updatedOperator; } /** - * Add operator entity via POST request + * Utility method for checking of some constraints during entity addition, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link io.khasang.ba.controller.utility.RestRequests#addEntityWithIncorrectField(Class, String, Object, HttpStatus)}. * - * @param operator {@link Operator} instance, which should be added via POST request - * @return {@link ResponseEntity} containing response data + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field */ - private ResponseEntity getResponseEntityFromPostRequest(Operator operator) { - HttpHeaders httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - HttpEntity httpEntity = new HttpEntity<>(operator, httpHeaders); - - RestTemplate restTemplate = new RestTemplate(); - return restTemplate.exchange( - ROOT + ADD, - HttpMethod.POST, - httpEntity, - Operator.class - ); + private void addWithIncorrectField(String fieldName, V incorrectValue) { + addEntityWithIncorrectField(Operator.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); } /** - * Static inner builder of operator + * Utility method for checking of some constraints during entity update, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link io.khasang.ba.controller.utility.RestRequests#updateEntityWithIncorrectField(Class, String, Object, HttpStatus)}. + * + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field */ - protected static class OperatorBuilder { - private OperatorInformation operatorInformation; - - //Instance of buildabe Operator - private Operator operator; - - public OperatorBuilder() { - operator = new Operator(); - operatorInformation = new OperatorInformation(); - operator.setOperatorInformation(operatorInformation); - } - - public Operator build() { - assertNotNull(operator.getLogin()); - assertNotNull(operator.getPassword()); - assertNotNull(operator.getEmail()); - return operator; - } - - public OperatorBuilder addLogin(String login) { - operator.setLogin(login); - return this; - } - - public OperatorBuilder addEmail(String email) { - operator.setEmail(email); - return this; - } - - public OperatorBuilder addPassword(String password) { - operator.setPassword(password); - return this; - } - - public OperatorBuilder addBirthDate(LocalDate birthDate) { - operatorInformation.setBirthDate(birthDate); - return this; - } - - public OperatorBuilder addFullName(String fullName) { - operatorInformation.setFullName(fullName); - return this; - } - - public OperatorBuilder addAbout(String about) { - operatorInformation.setAbout(about); - return this; - } - - public OperatorBuilder addCountry(String country) { - operatorInformation.setCountry(country); - return this; - } - - public OperatorBuilder addCity(String city) { - operatorInformation.setCity(city); - return this; - } + private void updateWithIncorrectField(String fieldName, V incorrectValue) { + updateEntityWithIncorrectField(Operator.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); } -} +} \ No newline at end of file diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java index 77ad280..c766316 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java @@ -40,13 +40,11 @@ public final class MockFactory { //Mock data for Operator private static final String TEST_OPERATOR_LOGIN_PREFIX = "TEST_OPERATOR_"; - private static final String TEST_OPERATOR_RAW_PASSWORD = "123tEsT#"; - private static final String TEST_OPERATOR_EMAIL_SUFFIX = "@ba.khasang.io"; - private static final String TEST_OPERATOR_FULL_NAME = "Ivan Petrov"; - private static final LocalDate TEST_OPERATOR_BIRTHDATE = LocalDate.of(1986, 8, 26); - private static final String TEST_OPERATOR_COUNTRY = "Russia"; - private static final String TEST_OPERATOR_CITY = "Saint Petersburg"; - private static final String TEST_OPERATOR_ABOUT = "Another one mock test operator"; + private static final String TEST_OPERATOR_EMAIL_SUFFIX = "@operator.khasang.io"; + private static final String TEST_OPERATOR_FULL_NAME_PREFIX = "Barak Obama "; + private static final String TEST_OPERATOR_COUNTRY_PREFIX = "USA "; + private static final String TEST_OPERATOR_CITY_PREFIX = "New York "; + private static final String TEST_OPERATOR_ABOUT_PREFIX = "Another one mock test operator "; //Mock data for CustomerRequestStage private static final String TEST_CUSTOMER_REQUEST_STAGE_DESCRIPTION = "Test description of the customer's request stage"; @@ -104,23 +102,43 @@ public static Customer getChangedMockCustomer(Customer oldCustomer) { * @return mock operator instance */ public static Operator getMockOperator() { + Random random = new Random(); Operator operator = new Operator(); OperatorInformation operatorInformation = new OperatorInformation(); operator.setLogin(TEST_OPERATOR_LOGIN_PREFIX + UUID.randomUUID().toString()); + operator.setPassword(UUID.randomUUID().toString()); operator.setEmail(UUID.randomUUID().toString() + TEST_OPERATOR_EMAIL_SUFFIX); - operator.setPassword(TEST_OPERATOR_RAW_PASSWORD); operator.setOperatorInformation(operatorInformation); - operatorInformation.setFullName(TEST_OPERATOR_FULL_NAME); - operatorInformation.setBirthDate(TEST_OPERATOR_BIRTHDATE); - operatorInformation.setCountry(TEST_OPERATOR_COUNTRY); - operatorInformation.setCity(TEST_OPERATOR_CITY); - operatorInformation.setAbout(TEST_OPERATOR_ABOUT); + operatorInformation.setFullName(TEST_OPERATOR_FULL_NAME_PREFIX + UUID.randomUUID().toString()); + operatorInformation.setBirthDate(LocalDate.ofYearDay( + 1930 + random.nextInt(71), + 1 + random.nextInt(365))); + operatorInformation.setCountry(TEST_OPERATOR_COUNTRY_PREFIX + UUID.randomUUID().toString()); + operatorInformation.setCity(TEST_OPERATOR_CITY_PREFIX + UUID.randomUUID().toString()); + operatorInformation.setAbout(TEST_OPERATOR_ABOUT_PREFIX + UUID.randomUUID().toString()); return operator; } + /** + * Change existing {@link Operator}. Firstly, new mock entity is made and then copying of necessary + * fields from old entity (generally with constraints Id, Unique, NaturalId etc) is performed. + * + * @param oldOperator old entity + * @return changed entity + */ + public static Operator getChangedMockOperator(Operator oldOperator) { + Operator newOperator = getMockOperator(); + + newOperator.setId(oldOperator.getId()); + newOperator.setLogin(oldOperator.getLogin()); + newOperator.setRegistrationTimestamp(oldOperator.getRegistrationTimestamp()); + + return newOperator; + } + /** * Create mock {@link CustomerRequestStage} instance * @@ -132,7 +150,7 @@ public static CustomerRequestStage getMockCustomerRequestStage() { List operatorList = getCreatedEntitiesList( Operator.class, RELATED_ENTITIES_AMOUNT, - HttpStatus.OK); + HttpStatus.CREATED); customerRequestStage.setComment(TEST_CUSTOMER_REQUEST_STAGE_DESCRIPTION); customerRequestStage.setOperators(operatorList); diff --git a/rest/src/main/java/io/khasang/ba/controller/OperatorController.java b/rest/src/main/java/io/khasang/ba/controller/OperatorController.java index ffb3ec8..f5f7ab9 100644 --- a/rest/src/main/java/io/khasang/ba/controller/OperatorController.java +++ b/rest/src/main/java/io/khasang/ba/controller/OperatorController.java @@ -3,7 +3,8 @@ import io.khasang.ba.entity.Operator; import io.khasang.ba.service.OperatorService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; @@ -11,40 +12,39 @@ /** * Controller for REST layer of Operator management: provided POST, GET, PUT and DELETE functionality */ -@Controller +@RestController @RequestMapping(value = "/operator") public class OperatorController { @Autowired private OperatorService operatorService; - @RequestMapping(value = "/add", method = RequestMethod.POST, produces = "application/json;charset=utf-8") - @ResponseBody + @PostMapping(value = "/add", consumes = "application/json;charset=utf-8") + @ResponseStatus(HttpStatus.CREATED) public Operator addOperator(@RequestBody Operator newOperator) { return operatorService.addOperator(newOperator); } - @RequestMapping(value = "/get/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - @ResponseBody - public Operator getOperatorById(@PathVariable(value = "id") long id) { - return operatorService.getOperatorById(id); + @GetMapping(value = "/get/{id}") + public ResponseEntity getOperatorById(@PathVariable(value = "id") long id) { + Operator operator = operatorService.getOperatorById(id); + + return (operator != null) ? ResponseEntity.ok(operator) : ResponseEntity.notFound().build(); } - @RequestMapping(value = "/update", method = RequestMethod.PUT, produces = "application/json;charset=utf-8") - @ResponseBody + @PutMapping(value = "/update", consumes = "application/json;charset=utf-8") public Operator updateOperator(@RequestBody Operator updatedOperator) { return operatorService.updateOperator(updatedOperator); } - @RequestMapping(value = "/get/all", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - @ResponseBody + @GetMapping(value = "/get/all") public List getAllOperators() { return operatorService.getAllOperators(); } - @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE, produces = "application/json;charset=utf-8") - @ResponseBody - public Operator deleteOperator(@PathVariable(value = "id") long id) { - return operatorService.deleteOperator(id); + @DeleteMapping(value = "/delete/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + public void deleteOperator(@PathVariable(value = "id") long id) { + operatorService.deleteOperator(id); } } diff --git a/rest/src/main/java/io/khasang/ba/entity/Operator.java b/rest/src/main/java/io/khasang/ba/entity/Operator.java index 8c13672..32da468 100644 --- a/rest/src/main/java/io/khasang/ba/entity/Operator.java +++ b/rest/src/main/java/io/khasang/ba/entity/Operator.java @@ -1,101 +1,41 @@ package io.khasang.ba.entity; +import lombok.Data; +import lombok.EqualsAndHashCode; import org.hibernate.annotations.NaturalId; -import org.hibernate.validator.constraints.NotEmpty; +import org.hibernate.validator.constraints.NotBlank; import javax.persistence.*; import java.time.LocalDateTime; -import java.util.Objects; /** - * Operator entity class. Operators in are users, handling customers' requests + * Operator entity class. Operators are users, handling customers' requests */ +@Data @Entity @Table(name = "operators") public class Operator { @Id @GeneratedValue(strategy = GenerationType.AUTO) + @EqualsAndHashCode.Exclude private Long id; - @NotEmpty + @NotBlank @NaturalId private String login; @Column(name = "registration_date", columnDefinition = "TIMESTAMP") + @EqualsAndHashCode.Exclude private LocalDateTime registrationTimestamp; - @NotEmpty + @NotBlank private String password; - @NotEmpty + @NotBlank @Column(unique = true) private String email; @Embedded private OperatorInformation operatorInformation; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getLogin() { - return login; - } - - public void setLogin(String login) { - this.login = login; - } - - public LocalDateTime getRegistrationTimestamp() { - return registrationTimestamp; - } - - public void setRegistrationTimestamp(LocalDateTime registrationTimestamp) { - this.registrationTimestamp = registrationTimestamp; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public OperatorInformation getOperatorInformation() { - return operatorInformation; - } - - public void setOperatorInformation(OperatorInformation operatorInformation) { - this.operatorInformation = operatorInformation; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Operator operator = (Operator) o; - return Objects.equals(login, operator.login) && - Objects.equals(password, operator.password) && - Objects.equals(email, operator.email) && - Objects.equals(operatorInformation, operator.operatorInformation); - } - - @Override - public int hashCode() { - return Objects.hash(login, password, email, operatorInformation); - } } diff --git a/rest/src/main/java/io/khasang/ba/entity/OperatorInformation.java b/rest/src/main/java/io/khasang/ba/entity/OperatorInformation.java index 11e7355..01dcb39 100644 --- a/rest/src/main/java/io/khasang/ba/entity/OperatorInformation.java +++ b/rest/src/main/java/io/khasang/ba/entity/OperatorInformation.java @@ -1,12 +1,14 @@ package io.khasang.ba.entity; +import lombok.Data; + import javax.persistence.Embeddable; import java.time.LocalDate; -import java.util.Objects; /** * Embeddable class with common information about operator, all field can be nullable and non unique */ +@Data @Embeddable public class OperatorInformation { @@ -19,61 +21,4 @@ public class OperatorInformation { private String city; private String about; - - public String getFullName() { - return fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } - - public LocalDate getBirthDate() { - return birthDate; - } - - public void setBirthDate(LocalDate birthDate) { - this.birthDate = birthDate; - } - - public String getCountry() { - return country; - } - - public void setCountry(String country) { - this.country = country; - } - - public String getCity() { - return city; - } - - public void setCity(String city) { - this.city = city; - } - - public String getAbout() { - return about; - } - - public void setAbout(String about) { - this.about = about; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - OperatorInformation that = (OperatorInformation) o; - return Objects.equals(fullName, that.fullName) && - Objects.equals(birthDate, that.birthDate) && - Objects.equals(country, that.country) && - Objects.equals(city, that.city) && - Objects.equals(about, that.about); - } - - @Override - public int hashCode() { - return Objects.hash(fullName, birthDate, country, city, about); - } } From 02105c55ec846049bb2af41d55a6bb0fc0adf40f Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Fri, 24 May 2019 22:11:45 +0300 Subject: [PATCH 18/28] - add lombok --- .../io/khasang/ba/entity/PointOfInterest.java | 89 +++---------------- 1 file changed, 14 insertions(+), 75 deletions(-) diff --git a/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java b/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java index 8975000..cf387df 100644 --- a/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java +++ b/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java @@ -1,7 +1,11 @@ package io.khasang.ba.entity; import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.NonNull; import org.hibernate.annotations.ColumnDefault; +import org.hibernate.validator.constraints.NotEmpty; import javax.persistence.*; import java.time.LocalTime; @@ -11,96 +15,31 @@ * include category etc. */ @Entity -@Table(name = "pointsOfInterest") +@Table(name = "points_of_interest") +@Data +@NoArgsConstructor public class PointOfInterest { @Id - @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; + @NonNull + @NotEmpty private String name; @ColumnDefault(value = "'unknown'") private String category; - @Column(columnDefinition = "TIME") + @Column(name = "start_work", columnDefinition = "TIME") @ColumnDefault(value = "'00:00:00'") @JsonFormat(pattern = "HH:mm") private LocalTime startWork; @ColumnDefault(value = "0") + @Column(name = "work_time") private int workTime; - private String address; - - //Geographic coordinates latitude - @ColumnDefault(value = "0.000000") - private double latitude; - - //Geographic coordinates longitude - @ColumnDefault(value = "0.000000") - private double longitude; - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getCategory() { - return category; - } - - public void setCategory(String category) { - this.category = category; - } - - public LocalTime getStartWork() { - return startWork; - } - public void setStartWork(LocalTime startWork) { - this.startWork = startWork; - } - - public int getWorkTime() { - return workTime; - } - - public void setWorkTime(int workTime) { - this.workTime = workTime >= 0 ? workTime : 0; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public double getLatitude() { - return latitude; - } - - public void setLatitude(double latitude) { - this.latitude = latitude; - } - - public double getLongitude() { - return longitude; - } - - public void setLongitude(double longitude) { - this.longitude = longitude; - } + @NonNull + private String address; } From 2a11e20082a7a19bb26af8099560f00fab7cebe1 Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Fri, 24 May 2019 22:34:13 +0300 Subject: [PATCH 19/28] - add lombok to Category --- .../java/io/khasang/ba/entity/Category.java | 40 ++++++------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/rest/src/main/java/io/khasang/ba/entity/Category.java b/rest/src/main/java/io/khasang/ba/entity/Category.java index 60180e3..38341ac 100644 --- a/rest/src/main/java/io/khasang/ba/entity/Category.java +++ b/rest/src/main/java/io/khasang/ba/entity/Category.java @@ -1,40 +1,26 @@ package io.khasang.ba.entity; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.NonNull; + import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; -import javax.validation.constraints.NotNull; + +/** + * Entity Category include some type as supermarket, restaurants, e.g. + */ @Entity +@Data +@NoArgsConstructor public class Category { @Id - @GeneratedValue(strategy = GenerationType.AUTO) + @GeneratedValue(strategy = GenerationType.IDENTITY) private long id; - @NotNull + @NonNull private String name; - - public Category() { - } - - public Category(String name) { - this.name = name; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } -} +} \ No newline at end of file From a0988216e388d33f8c9d91fc5c710ed9c803a7f8 Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Fri, 24 May 2019 22:39:46 +0300 Subject: [PATCH 20/28] - add lombok and embeddable to Address --- .../java/io/khasang/ba/entity/Address.java | 150 ------------------ .../khasang/ba/entity/embeddable/Address.java | 40 +++++ 2 files changed, 40 insertions(+), 150 deletions(-) delete mode 100644 rest/src/main/java/io/khasang/ba/entity/Address.java create mode 100644 rest/src/main/java/io/khasang/ba/entity/embeddable/Address.java diff --git a/rest/src/main/java/io/khasang/ba/entity/Address.java b/rest/src/main/java/io/khasang/ba/entity/Address.java deleted file mode 100644 index fc87f5e..0000000 --- a/rest/src/main/java/io/khasang/ba/entity/Address.java +++ /dev/null @@ -1,150 +0,0 @@ -package io.khasang.ba.entity; - -import org.hibernate.annotations.ColumnDefault; - -import javax.persistence.*; -import javax.validation.constraints.NotNull; -import java.util.ArrayList; -import java.util.List; - -/** - * This entity storages address something - * minimal requariment on input is City, Street and Hause. - */ - -@Entity -public class Address { - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - private long id; - - private String region; - - @NotNull - private String city; - - @NotNull - private String street; - private int postcode; - - @NotNull - private String hause; - - private String office; - - //Geographic coordinates latitude - @ColumnDefault(value = "0.000000") - private double latitude; - - //Geographic coordinates longitude - @ColumnDefault(value = "0.000000") - private double longitude; - - public Address() { - } - - public Address(String region, String city, String street, int postcode, String hause) { - this.region = region; - this.city = city; - this.street = street; - this.postcode = postcode; - this.hause = hause; - } - - public Address(String city, String street, String hause, String office) { - this.city = city; - this.street = street; - this.hause = hause; - this.office = office; - } - - public Address(String region, String city, String street, int postcode, String hause, String office, - double latitude, double longitude) { - this.region = region; - this.city = city; - this.street = street; - this.postcode = postcode; - this.hause = hause; - this.office = office; - this.latitude = latitude; - this.longitude = longitude; - } - - public Address(String city, String street, String hause) { - this.city = city; - this.street = street; - this.hause = hause; - } - - public long getId() { - return id; - } - - public void setId(long id) { - this.id = id; - } - - public String getRegion() { - return region; - } - - public void setRegion(String region) { - this.region = region; - } - - public String getCity() { - return city; - } - - public void setCity(String city) { - this.city = city; - } - - public String getStreet() { - return street; - } - - public void setStreet(String street) { - this.street = street; - } - - public int getPostcode() { - return postcode; - } - - public void setPostcode(int postcode) { - this.postcode = postcode; - } - - public String getHause() { - return hause; - } - - public void setHause(String hause) { - this.hause = hause; - } - - public String getOffice() { - return office; - } - - public void setOffice(String office) { - this.office = office; - } - - public double getLatitude() { - return latitude; - } - - public void setLatitude(double latitude) { - this.latitude = latitude; - } - - public double getLongitude() { - return longitude; - } - - public void setLongitude(double longitude) { - this.longitude = longitude; - } -} diff --git a/rest/src/main/java/io/khasang/ba/entity/embeddable/Address.java b/rest/src/main/java/io/khasang/ba/entity/embeddable/Address.java new file mode 100644 index 0000000..659c4d1 --- /dev/null +++ b/rest/src/main/java/io/khasang/ba/entity/embeddable/Address.java @@ -0,0 +1,40 @@ +package io.khasang.ba.entity.embeddable; + +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.NonNull; +import org.hibernate.annotations.ColumnDefault; + +import javax.persistence.Embeddable; + +/** + * This class storages address something + * minimal requariment on input is City, Street and Build. + */ + +@Embeddable +@Data +@NoArgsConstructor +public class Address { + private String region; + + @NonNull + private String city; + + @NonNull + private String street; + + private String postcode; + + @NonNull + private String build; + + @NonNull + private String room; + + @ColumnDefault(value = "0.000000") + private Double latitude; + + @ColumnDefault(value = "0.000000") + private Double longitude; +} From 6be7b5c4f357bd27b49a13ce8896313d5f75758a Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Fri, 24 May 2019 22:41:03 +0300 Subject: [PATCH 21/28] - fix problem type non-class --- rest/src/main/java/io/khasang/ba/entity/Category.java | 2 +- rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/rest/src/main/java/io/khasang/ba/entity/Category.java b/rest/src/main/java/io/khasang/ba/entity/Category.java index 38341ac..45a876e 100644 --- a/rest/src/main/java/io/khasang/ba/entity/Category.java +++ b/rest/src/main/java/io/khasang/ba/entity/Category.java @@ -19,7 +19,7 @@ public class Category { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private long id; + private Long id; @NonNull private String name; diff --git a/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java b/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java index cf387df..e01391f 100644 --- a/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java +++ b/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java @@ -22,7 +22,7 @@ public class PointOfInterest { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private long id; + private Long id; @NonNull @NotEmpty @@ -38,7 +38,7 @@ public class PointOfInterest { @ColumnDefault(value = "0") @Column(name = "work_time") - private int workTime; + private Integer workTime; @NonNull private String address; From 78ee6c6192698109692796d9b7375f86e06520cd Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Mon, 27 May 2019 22:55:19 +0300 Subject: [PATCH 22/28] - modify field name on unique and not blank --- rest/src/main/java/io/khasang/ba/entity/Category.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/rest/src/main/java/io/khasang/ba/entity/Category.java b/rest/src/main/java/io/khasang/ba/entity/Category.java index 45a876e..17ac718 100644 --- a/rest/src/main/java/io/khasang/ba/entity/Category.java +++ b/rest/src/main/java/io/khasang/ba/entity/Category.java @@ -3,6 +3,8 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.NonNull; +import org.hibernate.annotations.NaturalId; +import org.hibernate.validator.constraints.NotBlank; import javax.persistence.Entity; import javax.persistence.GeneratedValue; @@ -21,6 +23,7 @@ public class Category { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @NonNull + @NotBlank + @NaturalId private String name; } \ No newline at end of file From a60157f5e54e5efe5a308f8192c877bc23ff961c Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Mon, 27 May 2019 23:02:05 +0300 Subject: [PATCH 23/28] - modify entity to RestController - add ResponseStatus to method --- .../ba/controller/CategoryController.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/rest/src/main/java/io/khasang/ba/controller/CategoryController.java b/rest/src/main/java/io/khasang/ba/controller/CategoryController.java index 9326387..70c6835 100644 --- a/rest/src/main/java/io/khasang/ba/controller/CategoryController.java +++ b/rest/src/main/java/io/khasang/ba/controller/CategoryController.java @@ -3,43 +3,43 @@ import io.khasang.ba.entity.Category; import io.khasang.ba.service.CategoryService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; -@Controller +@RestController @RequestMapping(value = "/category") public class CategoryController { + @Autowired private CategoryService categoryService; - @RequestMapping(value = "/get/all", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - @ResponseBody - public List getAll() { - return categoryService.getAllCategories(); - } - - @RequestMapping(value = "/get/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - @ResponseBody - public Category getCategory(@PathVariable(value = "id") long id) { - return categoryService.getCategoryById(id); - } - - @RequestMapping(value = "/add", method = RequestMethod.POST, produces = "application/json;charset=utf-8") - @ResponseBody + @ResponseStatus(code = HttpStatus.CREATED) + @PostMapping(value = "/add", produces = "application/json;charset=utf-8") public Category addCategory(@RequestBody Category category) { return categoryService.addCategory(category); } - @RequestMapping(value = "/update", method = RequestMethod.PUT, produces = "application/json;charset=utf-8") - @ResponseBody + @GetMapping(value = "/get/{id}", produces = "application/json;charset=utf-8") + public ResponseEntity getCategoryById(@PathVariable(value = "id") long id) { + Category category = categoryService.getCategoryById(id); + return category == null ? ResponseEntity.notFound().build() : ResponseEntity.ok(category); + } + + @PutMapping(value = "/update", produces = "application/json;charset=utf-8") public Category updateCategory(@RequestBody Category category) { return categoryService.updateCategory(category); } - @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE, produces = "application/json;charset=utf-8") - @ResponseBody + @GetMapping(value = "/get/all", produces = "application/json;charset=utf-8") + public List getAllCategories() { + return categoryService.getAllCategories(); + } + + @ResponseStatus(code = HttpStatus.NO_CONTENT) + @DeleteMapping(value = "/delete/{id}", produces = "application/json;charset=utf-8") public Category deleteCategory(@PathVariable(value = "id") long id) { return categoryService.deleteCategory(id); } From 7ff58ec7cb014c9e9b8dc924b8c7be20d57499b0 Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Mon, 27 May 2019 23:08:04 +0300 Subject: [PATCH 24/28] - delete bean from AppConfig because Address change to Embedded --- rest/src/main/java/io/khasang/ba/config/AppConfig.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/rest/src/main/java/io/khasang/ba/config/AppConfig.java b/rest/src/main/java/io/khasang/ba/config/AppConfig.java index c6043d4..04d85e9 100644 --- a/rest/src/main/java/io/khasang/ba/config/AppConfig.java +++ b/rest/src/main/java/io/khasang/ba/config/AppConfig.java @@ -96,11 +96,6 @@ public CustomerRequestTypeDao customerRequestTypeDao() { return new CustomerRequestTypeDaoImpl(CustomerRequestType.class); } - @Bean - public AddressDao addressDao() { - return new AddressDaoImpl(Address.class); - } - @Bean public CategoryDao categoryDao() { return new CategoryDaoImpl(Category.class); From d064091361b2e52580f6211493ba4f691212b4e4 Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Tue, 28 May 2019 00:00:50 +0300 Subject: [PATCH 25/28] - modify Integration Tests for Category and PointOfInterest as Customer --- .../CategoryControllerIntegrationTest.java | 335 +++++++++--------- ...ntOfInterestControllerIntegrationTest.java | 321 ++++++++++------- .../ba/controller/utility/MockFactory.java | 93 +++++ .../ba/controller/utility/RestRequests.java | 13 +- 4 files changed, 454 insertions(+), 308 deletions(-) diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/CategoryControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/CategoryControllerIntegrationTest.java index d5a0f2f..0d226a3 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/CategoryControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/CategoryControllerIntegrationTest.java @@ -1,232 +1,233 @@ package io.khasang.ba.controller; import io.khasang.ba.entity.Category; -import org.junit.Assert; import org.junit.Test; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; -import org.springframework.web.client.RestTemplate; +import org.springframework.http.HttpStatus; -import java.util.ArrayList; import java.util.List; -public class CategoryControllerIntegrationTest { - private final String LAN_ADDRESS = "localhost"; - private final String PORT = "8080"; - private final String ROOT = "http://" + LAN_ADDRESS + ":" + PORT + "/category"; - private final String ADD = "/add"; - private final String GET = "/get"; - private final String ID = "/{id}"; - private final String ALL = "/all"; - private final String DELETE = "/delete"; - private final String UPDATE = "/update"; +import static io.khasang.ba.controller.utility.MockFactory.getChangedMockCategory; +import static io.khasang.ba.controller.utility.MockFactory.getMockCategory; +import static io.khasang.ba.controller.utility.RestRequests.*; +import static org.junit.Assert.*; +/** + * Integration test for Category REST layer + */ +public class CategoryControllerIntegrationTest { /** - * Test correct delete record into DB + * Check, that {@link CategoryController#getCategoryById(long)} gives NOT FOUND HTTP response + * in the case of attempt to get nonexistent entity, i.e. entity with nonexistent Id. */ @Test - public void deleteCategory() { - Category category; - ResponseEntity responseEntity; - category = prefillCategory(); - category = createCategory(category); - responseEntity = deleteCategoryById(category.getId()); - - // Check response is OK - Assert.assertEquals("Request is bad. Must be OK", "OK", responseEntity.getStatusCode().getReasonPhrase()); - - // Record must doesn't find into DB - Assert.assertNull("Entity doesn't delete into DB", getCategoryById(category.getId())); + public void checkGetNonExistentCategory() { + getEntityById(Long.MAX_VALUE, Category.class, HttpStatus.NOT_FOUND); } /** - * Test record entity - * Requset must be record. Data don't count + * Check both {@link CategoryController#getCategoryById(long)} and + * {@link CategoryController#addCategory(Category)} methods, + * i.e. HTTP methods GET and POST, providing possibilities to get an {@link Category} entity + * from REST resource and to add it to the resource. */ @Test - public void addCategory() { - Category category = prefillCategory(); - Category responseBodyCategory = createCategory(category); + public void checkAddCategory() { + + //POST to REST + Category createdCategory = getCreatedCategory(); - // Response create not null - Assert.assertNotNull("Response must be Entity", responseBodyCategory); - deleteCategoryById(responseBodyCategory.getId()); + // GET from REST + Category receivedCategory = + getEntityById( + createdCategory.getId(), + Category.class, + HttpStatus.OK); + + assertEquals(createdCategory, receivedCategory); } /** - * Read entity by Id - * @param id - id Entity - * @return entity + * Check {@link CategoryController#getAllCategories()} method, i.e. HTTP method GET, used to + * get a list of {@link Category} entities from REST resource + * entities.
+ *

First of all, continuous addition of {@link Category} entities with amount equal to + * {@link io.khasang.ba.controller.utility.RestRequests#TEST_ENTITIES_AMOUNT} is performed. + * Secondly, top TEST_ENTITIES_AMOUNT of entities, obtained from response body, received from REST-resource, placed at + * {@link io.khasang.ba.controller.utility.RestRequests#GET_ALL_PATH}), compared with list of + * previously added entities. + *

*/ - private Category getCategoryById(long id) { - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + GET + ID, - HttpMethod.GET, - null, - Category.class, - id - ); - Assert.assertEquals("Request is bad. Must be OK", "OK", responseEntity.getStatusCode().getReasonPhrase()); + @Test + public void checkGetAllCategories() { + + // Create list of entities + List createdCategorysList = + getCreatedEntitiesList( + Category.class, + TEST_ENTITIES_AMOUNT, + HttpStatus.CREATED); + + // Receive all entities from REST + List allCategorys = + getAllEntitiesList(Category.class, HttpStatus.OK); + + // Check last TEST_ENTITIES_AMOUNT and assert for equality + List receivedCategorysSubList = + allCategorys.subList(allCategorys.size() - TEST_ENTITIES_AMOUNT, + allCategorys.size()); - return responseEntity.getBody(); + assertEquals(createdCategorysList, receivedCategorysSubList); } /** - * Add new Address into DB - * Test equal source Address with added + * Check {@link CategoryController#updateCategory(Category)}, i.e. HTTP method + * PUT, used to update an {@link Category} entity on REST resource */ @Test - public void addCategoryWithEqualContent() { - Category category; - Category responseBodyCategory; - category = prefillCategory(); + public void checkUpdateCategory() { - responseBodyCategory = createCategory(category); + // POST, then UPDATE in REST + Category updatedCategory = getUpdatedCategory(); - // Equals two entity created and template - Assert.assertTrue("Fields don't equals. Must be equals", equals(category, responseBodyCategory)); - deleteCategoryById(responseBodyCategory.getId()); + //Get it from REST, check id and assertEquals + Category receivedCategory = + getEntityById( + updatedCategory.getId(), + Category.class, + HttpStatus.OK); + + assertNotNull(receivedCategory.getId()); + assertEquals(updatedCategory, receivedCategory); } /** - * Entity must update something self fields + * Check {@link CategoryController#deleteCategory(long)}, i.e. HTTP method + * DELETE, used to delete an {@link Category} entity on REST resource */ @Test - public void updateCategory() { - Category category; - Category responseCreatedCategory; - Category responseUpdateCategory; + public void checkCategoryDelete() { + Category createdCategory = getCreatedCategory(); - category = prefillCategory(); - responseCreatedCategory = createCategory(category); + getResponseFromEntityDeleteRequest( + createdCategory.getId(), + Category.class, + HttpStatus.NO_CONTENT); - // Change data - category.setName("name2"); - category.setId(responseCreatedCategory.getId()); - responseUpdateCategory = updateCategory(category); + assertNull(getEntityById( + createdCategory.getId(), + Category.class, + HttpStatus.NOT_FOUND)); + } - // Created address mustn't be equals updated address - Assert.assertFalse("Fields are equals. They must be don't equals", equals(responseCreatedCategory, responseUpdateCategory)); + //Addition constraints - // Delete entity into DB - deleteCategoryById(responseUpdateCategory.getId()); + /** + * Check unique constraint for name field while adding {@link Category} + */ + @Test + public void checkUniqueConstraintForName_whenCategoryRequestStageAdd() { + addWithIncorrectField("name", getCreatedCategory().getName()); } + /** + * Check not blank constraint for name while adding {@link Category} + */ @Test - public void getAllCategories() { - List categories; - - categories = new ArrayList<>(); - categories.add(createCategory(prefillCategory())); - categories.add(createCategory(prefillCategory())); - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity> responseEntity = restTemplate.exchange( - ROOT + GET + ALL, - HttpMethod.GET, - null, - new ParameterizedTypeReference>() { - } - ); - Assert.assertEquals("Request is bad. Must be OK", "OK", responseEntity.getStatusCode().getReasonPhrase()); - Assert.assertNotNull("Not all addresses were recieve. Must be more", categories.get(0)); - Assert.assertNotNull("Not all addresses were recieve. Must be more", categories.get(1)); - deleteCategoryById(categories.get(0).getId()); - deleteCategoryById(categories.get(1).getId()); + public void checkNotBlankConstraintForName_whenCategoryRequestStageAdd() { + addWithIncorrectField("name", null); + addWithIncorrectField("name", ""); + addWithIncorrectField("name", " "); + addWithIncorrectField("name", " "); + addWithIncorrectField("name", "\t"); + addWithIncorrectField("name", "\n"); } + // Update constraints + /** - * Create record into DB - * @param entity create entity - * @return responseBody + * Check unique constraint for name while updating {@link Category} */ - private Category createCategory(Category entity) { - RestTemplate restTemplate; - HttpHeaders httpHeaders; - HttpEntity httpEntity; - Category createdCategory; - - restTemplate = new RestTemplate(); - httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - httpEntity = new HttpEntity<>(entity, httpHeaders); - - createdCategory = restTemplate.exchange( - ROOT + ADD, - HttpMethod.POST, - httpEntity, - Category.class - ).getBody(); - - return createdCategory; + @Test + public void checkUniqueConstraintForName_whenCategoryRequestStageUpdate() { + updateWithIncorrectField("name", getCreatedCategory().getName()); } /** - * Update record into DB - * @param entity update entity - * @return response body + * Check not blank constraint for name while updating {@link Category} */ - private Category updateCategory(Category entity) { - RestTemplate restTemplate; - HttpHeaders httpHeaders; - HttpEntity httpEntity; - Category updateCategory; - - restTemplate = new RestTemplate(); - httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - httpEntity = new HttpEntity<>(entity, httpHeaders); - - updateCategory = restTemplate.exchange( - ROOT + UPDATE, - HttpMethod.PUT, - httpEntity, - Category.class - ).getBody(); - - return updateCategory; + @Test + public void checkNotBlankConstraintForName_whenCategoryRequestStageUpdate() { + updateWithIncorrectField("name", null); + updateWithIncorrectField("name", ""); + updateWithIncorrectField("name", " "); + updateWithIncorrectField("name", " "); + updateWithIncorrectField("name", "\t"); + updateWithIncorrectField("name", "\n"); } + // Utility methods + /** - * Delete entity into DB by Id - * @param id - id entity - * @return response action + * Create mock {@link Category} instance, and add (i.e. POST) it to a REST resource + * + * @return added to REST resource entity */ - private ResponseEntity deleteCategoryById(long id) { - RestTemplate restTemplate; - restTemplate = new RestTemplate(); - - return restTemplate.exchange( - ROOT + DELETE + ID, - HttpMethod.DELETE, - null, - Category.class, - id - ); + private Category getCreatedCategory() { + Category Category = getMockCategory(); + + Category createdCategory = + getResponseFromEntityAddRequest(Category, HttpStatus.CREATED); + + assertNotNull(createdCategory.getId()); + Category.setId(createdCategory.getId()); + assertEquals(Category, createdCategory); + + return createdCategory; } /** - * Create and fill Category - * @return created Category + * Update existing {@link Category} entity at REST resource. Firstly, add new mock entity and then + * PUT updated entity to REST resource + * + * @return updated at REST resource instance of entity */ - private Category prefillCategory() { - return new Category("Hospital"); + private Category getUpdatedCategory() { + Category createdCategory = getCreatedCategory(); + + Category updatedCategory = + getResponseFromEntityUpdateRequest( + getChangedMockCategory(createdCategory), + HttpStatus.OK); + + assertEquals(createdCategory.getId(), updatedCategory.getId()); + + return updatedCategory; } /** - * Compare Category entity - * @param source - source entity - * @param target - equals entity - * @return is equals? + * Utility method for checking of some constraints during entity addition, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link io.khasang.ba.controller.utility.RestRequests#addEntityWithIncorrectField(Class, String, Object, HttpStatus)}. + * + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field */ - private boolean equals(Category source, Category target) { - boolean isCheck = false; - - if ( source.getName().equals(target.getName())) { - isCheck = true; - } + private void addWithIncorrectField(String fieldName, V incorrectValue) { + addEntityWithIncorrectField(Category.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); + } - return isCheck; + /** + * Utility method for checking of some constraints during entity update, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link io.khasang.ba.controller.utility.RestRequests#updateEntityWithIncorrectField(Class, String, Object, HttpStatus)}. + * + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field + */ + private void updateWithIncorrectField(String fieldName, V incorrectValue) { + updateEntityWithIncorrectField(Category.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); } } diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/PointOfInterestControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/PointOfInterestControllerIntegrationTest.java index e2fbdf5..b4caa70 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/PointOfInterestControllerIntegrationTest.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/PointOfInterestControllerIntegrationTest.java @@ -1,170 +1,217 @@ package io.khasang.ba.controller; import io.khasang.ba.entity.PointOfInterest; -import org.junit.Assert; import org.junit.Test; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; -import org.springframework.web.client.RestTemplate; +import org.springframework.http.HttpStatus; -import java.time.LocalTime; -import java.util.ArrayList; import java.util.List; +import static io.khasang.ba.controller.utility.MockFactory.getChangedMockPointOfInterest; +import static io.khasang.ba.controller.utility.MockFactory.getMockPointOfInterest; +import static io.khasang.ba.controller.utility.RestRequests.*; +import static org.junit.Assert.*; + +/** + * Integration test for PointOfInterest REST layer + */ public class PointOfInterestControllerIntegrationTest { - private final String LAN_ADDRESS = "localhost"; - private final String PORT = "8080"; - private final String ROOT = "http://" + LAN_ADDRESS + ":" + PORT + "/pointOfInterest"; - private final String ADD = "/add"; - private final String GET = "/get"; - private final String ID = "/{id}"; - private final String ALL = "/all"; - private final String DELETE = "/delete"; - private final String UPDATE = "/update"; + /** + * Check, that {@link PointOfInterestController#getPointOfInterestById(long)} gives NOT FOUND HTTP response + * in the case of attempt to get nonexistent entity, i.e. entity with nonexistent Id. + */ @Test - public void addPointOfInterest() { - PointOfInterest pointOfInterest; - long pointOfInterestCreateId; - PointOfInterest pointOfInterestGetById; - - pointOfInterest = createPointOfInterest(); - pointOfInterestCreateId = pointOfInterest.getId(); - pointOfInterestGetById = getPointOfInterestById(pointOfInterestCreateId); - Assert.assertNotNull(pointOfInterestGetById); - deletePointOfInterestById(pointOfInterestCreateId); - pointOfInterestGetById = getPointOfInterestById(pointOfInterestCreateId); - Assert.assertNull(pointOfInterestGetById); + public void checkGetNonExistentPointOfInterest() { + getEntityById(Long.MAX_VALUE, PointOfInterest.class, HttpStatus.NOT_FOUND); } - private ResponseEntity deletePointOfInterestById(long id) { - RestTemplate restTemplate; + /** + * Check both {@link PointOfInterestController#getPointOfInterestById(long)} and + * {@link PointOfInterestController#addPointOfInterest(PointOfInterest)} methods, + * i.e. HTTP methods GET and POST, providing possibilities to get an {@link PointOfInterest} entity + * from REST resource and to add it to the resource. + */ + @Test + public void checkAddPointOfInterest() { + + //POST to REST + PointOfInterest createdPointOfInterest = getCreatedPointOfInterest(); - restTemplate = new RestTemplate(); + // GET from REST + PointOfInterest receivedPointOfInterest = + getEntityById( + createdPointOfInterest.getId(), + PointOfInterest.class, + HttpStatus.OK); - @SuppressWarnings("METHOD") - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + DELETE + ID, - HttpMethod.DELETE, - null, - PointOfInterest.class, - id - ); - return responseEntity; + assertEquals(createdPointOfInterest, receivedPointOfInterest); + } + + /** + * Check {@link PointOfInterestController#getAllPointOfInterests()} method, i.e. HTTP method GET, used to + * get a list of {@link PointOfInterest} entities from REST resource + * entities.
+ *

First of all, continuous addition of {@link PointOfInterest} entities with amount equal to + * {@link io.khasang.ba.controller.utility.RestRequests#TEST_ENTITIES_AMOUNT} is performed. + * Secondly, top TEST_ENTITIES_AMOUNT of entities, obtained from response body, received from REST-resource, placed at + * {@link io.khasang.ba.controller.utility.RestRequests#GET_ALL_PATH}), compared with list of + * previously added entities. + *

+ */ + @Test + public void checkGetAllPointOfInterests() { + + // Create list of entities + List createdPointOfInterestsList = + getCreatedEntitiesList( + PointOfInterest.class, + TEST_ENTITIES_AMOUNT, + HttpStatus.CREATED); + + // Receive all entities from REST + List allPointOfInterests = + getAllEntitiesList(PointOfInterest.class, HttpStatus.OK); + + // Check last TEST_ENTITIES_AMOUNT and assert for equality + List receivedPointOfInterestsSubList = + allPointOfInterests.subList(allPointOfInterests.size() - TEST_ENTITIES_AMOUNT, + allPointOfInterests.size()); + + assertEquals(createdPointOfInterestsList, receivedPointOfInterestsSubList); + } + + /** + * Check {@link PointOfInterestController#updatePointOfInterest(PointOfInterest)}, i.e. HTTP method + * PUT, used to update an {@link PointOfInterest} entity on REST resource + */ + @Test + public void checkUpdatePointOfInterest() { + + // POST, then UPDATE in REST + PointOfInterest updatedPointOfInterest = getUpdatedPointOfInterest(); + + //Get it from REST, check id and assertEquals + PointOfInterest receivedPointOfInterest = + getEntityById( + updatedPointOfInterest.getId(), + PointOfInterest.class, + HttpStatus.OK); + + assertNotNull(receivedPointOfInterest.getId()); + assertEquals(updatedPointOfInterest, receivedPointOfInterest); } + /** + * Check {@link PointOfInterestController#deletePointOfInterest(long)}, i.e. HTTP method + * DELETE, used to delete an {@link PointOfInterest} entity on REST resource + */ @Test - public void deletePointOfInterest() { - PointOfInterest pointOfInterest; + public void checkPointOfInterestDelete() { + PointOfInterest createdPointOfInterest = getCreatedPointOfInterest(); + + getResponseFromEntityDeleteRequest( + createdPointOfInterest.getId(), + PointOfInterest.class, + HttpStatus.NO_CONTENT); - pointOfInterest = createPointOfInterest(); - ResponseEntity responseEntity = deletePointOfInterestById(pointOfInterest.getId()); - Assert.assertEquals("OK", responseEntity.getStatusCode().getReasonPhrase()); - Assert.assertNull(getPointOfInterestById(pointOfInterest.getId())); + assertNull(getEntityById( + createdPointOfInterest.getId(), + PointOfInterest.class, + HttpStatus.NOT_FOUND)); } + //Addition constraints + + /** + * Check not blank constraint for name while adding {@link PointOfInterest} + */ @Test - public void getAllPointOfInterest() { - List pointOfInterests; - - pointOfInterests = new ArrayList<>(); - pointOfInterests.add(createPointOfInterest()); - pointOfInterests.add(createPointOfInterest()); - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity> responseEntity = restTemplate.exchange( - ROOT + GET + ALL, - HttpMethod.GET, - null, - new ParameterizedTypeReference>() { - } - ); - Assert.assertEquals("OK", responseEntity.getStatusCode().getReasonPhrase()); - Assert.assertNotNull(pointOfInterests.get(0)); - Assert.assertNotNull(pointOfInterests.get(1)); - deletePointOfInterestById(pointOfInterests.get(0).getId()); - deletePointOfInterestById(pointOfInterests.get(1).getId()); - Assert.assertNull(getPointOfInterestById(pointOfInterests.get(0).getId())); - Assert.assertNull(getPointOfInterestById(pointOfInterests.get(1).getId())); + public void checkNotBlankConstraintForName_whenPointOfInterestRequestStageAdd() { + addWithIncorrectField("name", null); + addWithIncorrectField("name", ""); + addWithIncorrectField("name", " "); + addWithIncorrectField("name", " "); + addWithIncorrectField("name", "\t"); + addWithIncorrectField("name", "\n"); } + // Update constraints + + /** + * Check not blank constraint for name while updating {@link PointOfInterest} + */ @Test - public void updatePointOfInterest() { - PointOfInterest pointOfInterest; - RestTemplate restTemplate; - HttpHeaders httpHeaders; - HttpEntity entity; - - pointOfInterest = createPointOfInterest(); - restTemplate = new RestTemplate(); - httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - - //Change value column entity pointOfInterest - pointOfInterest.setName("newTest"); - pointOfInterest.setLatitude(54.333678); - entity = new HttpEntity<>(pointOfInterest, httpHeaders); - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + UPDATE, - HttpMethod.PUT, - entity, - PointOfInterest.class - ); - Assert.assertEquals("OK", responseEntity.getStatusCode().getReasonPhrase()); - Assert.assertNotNull(responseEntity.getBody()); - Assert.assertEquals("newTest", responseEntity.getBody().getName()); - Assert.assertEquals("54.333678", String.valueOf(responseEntity.getBody().getLatitude())); - deletePointOfInterestById(responseEntity.getBody().getId()); - Assert.assertNull(getPointOfInterestById(responseEntity.getBody().getId())); + public void checkNotBlankConstraintForName_whenPointOfInterestRequestStageUpdate() { + updateWithIncorrectField("name", null); + updateWithIncorrectField("name", ""); + updateWithIncorrectField("name", " "); + updateWithIncorrectField("name", " "); + updateWithIncorrectField("name", "\t"); + updateWithIncorrectField("name", "\n"); } - private PointOfInterest createPointOfInterest() { - PointOfInterest createdPointOfInterest; - PointOfInterest pointOfInterest; - RestTemplate restTemplate; - HttpHeaders httpHeaders; - HttpEntity entity; - restTemplate = new RestTemplate(); - httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - pointOfInterest = prefillPointOfInterest(); - entity = new HttpEntity<>(pointOfInterest, httpHeaders); - createdPointOfInterest = restTemplate.exchange( - ROOT + ADD, - HttpMethod.POST, - entity, - PointOfInterest.class - ).getBody(); - - // Check POST REST add new pointOfInterest - Assert.assertNotNull(createdPointOfInterest); - Assert.assertTrue(createdPointOfInterest.getId() >= 0); + // Utility methods + + /** + * Create mock {@link PointOfInterest} instance, and add (i.e. POST) it to a REST resource + * + * @return added to REST resource entity + */ + private PointOfInterest getCreatedPointOfInterest() { + PointOfInterest pointOfInterest = getMockPointOfInterest(); + + PointOfInterest createdPointOfInterest = + getResponseFromEntityAddRequest(pointOfInterest, HttpStatus.CREATED); + + assertNotNull(createdPointOfInterest.getId()); + pointOfInterest.setId(createdPointOfInterest.getId()); + assertEquals(pointOfInterest, createdPointOfInterest); + return createdPointOfInterest; } - private PointOfInterest prefillPointOfInterest() { - PointOfInterest pointOfInterest = new PointOfInterest(); - pointOfInterest.setCategory("testCategory"); - pointOfInterest.setAddress("testAddress"); - pointOfInterest.setLatitude(0.456000); - pointOfInterest.setLongitude(3.123456); - pointOfInterest.setName("testShop"); - pointOfInterest.setStartWork(LocalTime.of(9, 30)); - - // 8 hour (input value of min) - pointOfInterest.setWorkTime(8 * 60); - return pointOfInterest; + /** + * Update existing {@link PointOfInterest} entity at REST resource. Firstly, add new mock entity and then + * PUT updated entity to REST resource + * + * @return updated at REST resource instance of entity + */ + private PointOfInterest getUpdatedPointOfInterest() { + PointOfInterest createdPointOfInterest = getCreatedPointOfInterest(); + + PointOfInterest updatedPointOfInterest = + getResponseFromEntityUpdateRequest( + getChangedMockPointOfInterest(createdPointOfInterest), + HttpStatus.OK); + + assertEquals(createdPointOfInterest.getId(), updatedPointOfInterest.getId()); + + return updatedPointOfInterest; + } + + /** + * Utility method for checking of some constraints during entity addition, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link io.khasang.ba.controller.utility.RestRequests#addEntityWithIncorrectField(Class, String, Object, HttpStatus)}. + * + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field + */ + private void addWithIncorrectField(String fieldName, V incorrectValue) { + addEntityWithIncorrectField(PointOfInterest.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); } - private PointOfInterest getPointOfInterestById(long id) { - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity responseEntity = restTemplate.exchange( - ROOT + GET + ID, - HttpMethod.GET, - null, - PointOfInterest.class, - id - ); - Assert.assertEquals("OK", responseEntity.getStatusCode().getReasonPhrase()); - return responseEntity.getBody(); + /** + * Utility method for checking of some constraints during entity update, which has simpler signature + * with reduced number of parameters. It could be used instead of + * direct call of {@link io.khasang.ba.controller.utility.RestRequests#updateEntityWithIncorrectField(Class, String, Object, HttpStatus)}. + * + * @param fieldName field, which should be set with incorrect value + * @param incorrectValue incorrect value + * @param type of the field + */ + private void updateWithIncorrectField(String fieldName, V incorrectValue) { + updateEntityWithIncorrectField(PointOfInterest.class, fieldName, incorrectValue, HttpStatus.INTERNAL_SERVER_ERROR); } } diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java index c766316..7aaaa0b 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/MockFactory.java @@ -1,9 +1,12 @@ package io.khasang.ba.controller.utility; +import com.sun.corba.se.impl.protocol.giopmsgheaders.TargetAddress; import io.khasang.ba.entity.*; +import io.khasang.ba.entity.embeddable.Address; import org.springframework.http.HttpStatus; import java.time.LocalDate; +import java.time.LocalTime; import java.util.*; import java.util.function.Supplier; @@ -24,10 +27,12 @@ public final class MockFactory { * because its' supplier will be detected automatically */ public static final Map, Supplier> mockSuppliersMap = Collections.unmodifiableMap(new HashMap, Supplier>() {{ + put(Category.class, MockFactory::getMockCategory); put(Customer.class, MockFactory::getMockCustomer); put(CustomerRequestStage.class, MockFactory::getMockCustomerRequestStage); put(CustomerRequestStageName.class, MockFactory::getMockCustomerRequestStageName); put(Operator.class, MockFactory::getMockOperator); + put(PointOfInterest.class, MockFactory::getMockPointOfInterest); }}); //Mock data for Customer @@ -53,6 +58,24 @@ public final class MockFactory { private static final String TEST_CUSTOMER_REQUEST_STAGE_NAME_NAME_PREFIX = "TEST_STAGE_NAME_PREFIX_"; private static final String TEST_CUSTOMER_REQUEST_STAGE_NAME_DESCRIPTION_PREFIX = "Customer's request stage name: "; + //Mock data for PointOfInterest + private static final String TEST_POINT_OF_INTEREST_NAME = "OOO \"CALAMBUR\""; + private static final String TEST_POINT_OF_INTEREST_CATEGORY = "SuperMarket"; + private static final LocalTime TEST_POINT_OF_INTEREST_STRAT_WORK = LocalTime.of(9, 30); + private static final Integer TEST_POINT_OF_INTEREST_WORK_TIME = 9 * 60; + private static final String TEST_POINT_OF_INTEREST_ADDRESS = "Moscow, str. Pushkina 10"; + private static final String TEST_POINT_OF_INTEREST_REGION = "Moscow region"; + private static final String TEST_POINT_OF_INTEREST_CITY = "Moscow"; + private static final String TEST_POINT_OF_INTEREST_STREET = "Pushkina"; + private static final String TEST_POINT_OF_INTEREST_POSTCODE = "111333"; + private static final String TEST_POINT_OF_INTEREST_BUILD = "134"; + private static final String TEST_POINT_OF_INTEREST_ROOM = "10"; + private static final Double TEST_POINT_OF_INTEREST_LATITUDE = 10.321562D; + private static final Double TEST_POINT_OF_INTEREST_LONGITUDE = 25.321456D; + + //Mock data for Category + private static final String TEST_CATEGORY_NAME_PREFIX = "CATEGORY_IS_"; + /** * Create mock {@link Customer} instance * @@ -203,4 +226,74 @@ public static CustomerRequestStageName getChangedMockCustomerRequestStageName(Cu return newCustomerRequestStageName; } + + /** + * Create mock {@link PointOfInterest} instance + * + * @return mock {@link PointOfInterest} instance + */ + public static PointOfInterest getMockPointOfInterest() { + PointOfInterest pointOfInterest = new PointOfInterest(); + Address address = new Address(); + + pointOfInterest.setName(TEST_POINT_OF_INTEREST_NAME); + pointOfInterest.setStartWork(TEST_POINT_OF_INTEREST_STRAT_WORK); + pointOfInterest.setCategory(TEST_POINT_OF_INTEREST_CATEGORY); + pointOfInterest.setWorkTime(TEST_POINT_OF_INTEREST_WORK_TIME); + pointOfInterest.setAddress(address); + address.setRegion(TEST_POINT_OF_INTEREST_REGION); + address.setStreet(TEST_POINT_OF_INTEREST_STREET); + address.setCity(TEST_POINT_OF_INTEREST_CITY); + address.setBuild(TEST_POINT_OF_INTEREST_BUILD); + address.setLatitude(TEST_POINT_OF_INTEREST_LATITUDE); + address.setLongitude(TEST_POINT_OF_INTEREST_LONGITUDE); + address.setPostcode(TEST_POINT_OF_INTEREST_POSTCODE); + address.setRoom(TEST_POINT_OF_INTEREST_ROOM); + + return pointOfInterest; + } + + /** + * Change existing {@link PointOfInterest}. Firstly, new mock entity is made and then copying of necessary + * fields from old entity (generally with constraints Id, Unique, NaturalId etc) is performed. + * + * @param oldPointOfInterest old entity + * @return changed entity + */ + public static PointOfInterest getChangedMockPointOfInterest(PointOfInterest oldPointOfInterest) { + PointOfInterest newPointOfInterest = getMockPointOfInterest(); + + newPointOfInterest.setId(oldPointOfInterest.getId()); + + return newPointOfInterest; + } + + /** + * Create mock {@link Category} instance + * + * @return mock {@link Category} instance + */ + public static Category getMockCategory() { + Category category = new Category(); + + category.setName(TEST_CATEGORY_NAME_PREFIX + UUID.randomUUID().toString()); + + return category; + } + + /** + * Change existing {@link Category}. Firstly, new mock entity is made and then copying of necessary + * fields from old entity (generally with constraints Id, Unique, NaturalId etc) is performed. + * + * @param oldCategory old entity + * @return changed entity + */ + public static Category getChangedMockCategory(Category oldCategory) { + Category newCategory = getMockCategory(); + + newCategory.setId(oldCategory.getId()); + newCategory.setName(oldCategory.getName()); + + return newCategory; + } } diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java index b8bb2eb..9964ca2 100644 --- a/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java +++ b/integrationtest/src/test/java/io/khasang/ba/controller/utility/RestRequests.java @@ -1,9 +1,6 @@ package io.khasang.ba.controller.utility; -import io.khasang.ba.entity.Customer; -import io.khasang.ba.entity.CustomerRequestStage; -import io.khasang.ba.entity.CustomerRequestStageName; -import io.khasang.ba.entity.Operator; +import io.khasang.ba.entity.*; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.*; import org.springframework.web.client.HttpClientErrorException; @@ -38,10 +35,12 @@ public final class RestRequests { public static String REST_ROOT = "http://localhost:8080/"; // Roots of REST resources + public static final String CATEGORY_ROOT = REST_ROOT + "category"; public static final String CUSTOMER_ROOT = REST_ROOT + "customer"; public static final String CUSTOMER_REQUEST_STAGE_ROOT = REST_ROOT + "customer_request_stage"; public static final String CUSTOMER_REQUEST_STAGE_NAME_ROOT = REST_ROOT + "customer_request_stage_name"; public static final String OPERATOR_ROOT = REST_ROOT + "operator"; + public static final String POINT_OF_INTEREST_ROOT = REST_ROOT + "pointOfInterest"; // Common addresses of REST resources public static final String ADD_PATH = "/add"; @@ -55,10 +54,12 @@ public final class RestRequests { * of the REST resource, because it will be detected automatically */ public static final Map, String> restRootsMap = Collections.unmodifiableMap(new HashMap, String>() {{ + put(Category.class, CATEGORY_ROOT); put(Customer.class, CUSTOMER_ROOT); put(CustomerRequestStage.class, CUSTOMER_REQUEST_STAGE_ROOT); put(CustomerRequestStageName.class, CUSTOMER_REQUEST_STAGE_NAME_ROOT); put(Operator.class, OPERATOR_ROOT); + put(PointOfInterest.class, POINT_OF_INTEREST_ROOT); }}); /** @@ -66,6 +67,8 @@ public final class RestRequests { */ public static final Map, ParameterizedTypeReference> typeReferencesMap = new HashMap, ParameterizedTypeReference>() {{ + put(Category.class, new ParameterizedTypeReference>() { + }); put(Customer.class, new ParameterizedTypeReference>() { }); put(CustomerRequestStage.class, new ParameterizedTypeReference>() { @@ -74,6 +77,8 @@ public final class RestRequests { }); put(Operator.class, new ParameterizedTypeReference>() { }); + put(PointOfInterest.class, new ParameterizedTypeReference>() { + }); }}; /** From 9670b342a2f9cf12e2b9d6961f5406354f385f98 Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Tue, 28 May 2019 00:02:15 +0300 Subject: [PATCH 26/28] - add RestController, ResponseStatus --- .../controller/PointOfInterestController.java | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/rest/src/main/java/io/khasang/ba/controller/PointOfInterestController.java b/rest/src/main/java/io/khasang/ba/controller/PointOfInterestController.java index ccd8475..cfac0f9 100644 --- a/rest/src/main/java/io/khasang/ba/controller/PointOfInterestController.java +++ b/rest/src/main/java/io/khasang/ba/controller/PointOfInterestController.java @@ -3,45 +3,44 @@ import io.khasang.ba.entity.PointOfInterest; import io.khasang.ba.service.PointOfInterestService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import java.util.List; -@Controller +@RestController @RequestMapping("/pointOfInterest") public class PointOfInterestController { @Autowired PointOfInterestService pointOfInterestService; - @RequestMapping(value = "/add", method = RequestMethod.POST, produces = "application/json;charset=utf-8") - @ResponseBody + @ResponseStatus(code = HttpStatus.CREATED) + @PostMapping(value = "/add", produces = "application/json;charset=utf-8") public PointOfInterest addPointOfInterest(@RequestBody PointOfInterest pointOfInterest) { pointOfInterestService.addPointOfInterest(pointOfInterest); return pointOfInterest; } - @ResponseBody - @RequestMapping(value = "/get/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - public PointOfInterest getPointOfInterestById(@PathVariable(value = "id") long id) { - return pointOfInterestService.getPointOfInterestById(id); + @GetMapping(value = "/get/{id}", produces = "application/json;charset=utf-8") + public ResponseEntity getPointOfInterestById(@PathVariable(value = "id") long id) { + PointOfInterest pointOfInterest = pointOfInterestService.getPointOfInterestById(id); + return pointOfInterest == null ? ResponseEntity.notFound().build() : ResponseEntity.ok(pointOfInterest); } - @ResponseBody - @RequestMapping(value = "/get/all", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - public List getAllPointOfInterests() { - return pointOfInterestService.getAllPointOfInterest(); - } - - @ResponseBody - @RequestMapping(value = "/update", method = RequestMethod.PUT, produces = "application/json;charset=utf-8") + @PutMapping(value = "/update", produces = "application/json;charset=utf-8") public PointOfInterest updatePointOfInterest(@RequestBody PointOfInterest pointOfInterest) { return pointOfInterestService.updatePointOfInterest(pointOfInterest); } - @ResponseBody - @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE, produces = "application/json;charset=utf-8") + @GetMapping(value = "/get/all", produces = "application/json;charset=utf-8") + public List getAllPointOfInterests() { + return pointOfInterestService.getAllPointOfInterest(); + } + + @ResponseStatus(code = HttpStatus.NO_CONTENT) + @DeleteMapping(value = "/delete/{id}", produces = "application/json;charset=utf-8") public PointOfInterest deletePointOfInterest(@PathVariable(value = "id") long id) { return pointOfInterestService.deletePointOfInterest(id); } From 5e1943722a28f00dd558ec598e27d5e7b71e1f9f Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Tue, 28 May 2019 00:04:16 +0300 Subject: [PATCH 27/28] - add Address to PointOfInterest; - remove Addres of DAO, Service and Controller; --- .../AddressControllerIntegrationTest.java | 256 ------------------ .../ba/controller/AddressController.java | 46 ---- .../java/io/khasang/ba/dao/AddressDao.java | 6 - .../khasang/ba/dao/impl/AddressDaoImpl.java | 10 - .../io/khasang/ba/entity/PointOfInterest.java | 11 +- .../khasang/ba/entity/embeddable/Address.java | 9 +- .../io/khasang/ba/service/AddressService.java | 46 ---- .../ba/service/impl/AddressServiceImpl.java | 40 --- 8 files changed, 9 insertions(+), 415 deletions(-) delete mode 100644 integrationtest/src/test/java/io/khasang/ba/controller/AddressControllerIntegrationTest.java delete mode 100644 rest/src/main/java/io/khasang/ba/controller/AddressController.java delete mode 100644 rest/src/main/java/io/khasang/ba/dao/AddressDao.java delete mode 100644 rest/src/main/java/io/khasang/ba/dao/impl/AddressDaoImpl.java delete mode 100644 rest/src/main/java/io/khasang/ba/service/AddressService.java delete mode 100644 rest/src/main/java/io/khasang/ba/service/impl/AddressServiceImpl.java diff --git a/integrationtest/src/test/java/io/khasang/ba/controller/AddressControllerIntegrationTest.java b/integrationtest/src/test/java/io/khasang/ba/controller/AddressControllerIntegrationTest.java deleted file mode 100644 index a895dd8..0000000 --- a/integrationtest/src/test/java/io/khasang/ba/controller/AddressControllerIntegrationTest.java +++ /dev/null @@ -1,256 +0,0 @@ -package io.khasang.ba.controller; - -import io.khasang.ba.entity.Address; -import org.junit.Assert; -import org.junit.Test; -import org.springframework.core.ParameterizedTypeReference; -import org.springframework.http.*; -import org.springframework.web.client.RestTemplate; - -import java.util.ArrayList; -import java.util.List; - -public class AddressControllerIntegrationTest { - private final String LAN_ADDRESS = "localhost"; - private final String PORT = "8080"; - private final String ROOT = "http://" + LAN_ADDRESS + ":" + PORT + "/address"; - private final String ADD = "/add"; - private final String GET = "/get"; - private final String ID = "/{id}"; - private final String ALL = "/all"; - private final String DELETE = "/delete"; - private final String UPDATE = "/update"; - - - /** - * Test correct delete record into DB - */ - @Test - public void deleteAddress() { - Address address; - ResponseEntity
responseEntity; - address = prefillAddress(); - address = createAddress(address); - responseEntity = deleteAddressById(address.getId()); - - // Check response is OK - Assert.assertEquals("Request is bad. Must be OK", "OK", responseEntity.getStatusCode().getReasonPhrase()); - - // Record must doesn't find into DB - Assert.assertNull("Entity doesn't delete into DB", getAddressById(address.getId())); - } - - /** - * Test record entity - * Requset must be record. Data don't count - */ - @Test - public void addAddress() { - Address address; - Address responseBodyAddress; - address = prefillAddress(); - - responseBodyAddress = createAddress(address); - - // Response create not null - Assert.assertNotNull("Response must be Entity", responseBodyAddress); - deleteAddressById(responseBodyAddress.getId()); - } - - /** - * Read entity by Id - * @param id - id Entity - * @return entity - */ - private Address getAddressById(long id) { - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity
responseEntity = restTemplate.exchange( - ROOT + GET + ID, - HttpMethod.GET, - null, - Address.class, - id - ); - Assert.assertEquals("Request is bad. Must be OK", "OK", responseEntity.getStatusCode().getReasonPhrase()); - - return responseEntity.getBody(); - } - - /** - * Add new Address into DB - * Test equal source Address with added - */ - @Test - public void addAddressWithEqualContent() { - Address address; - Address responseBodyAddress; - address = prefillAddress(); - - responseBodyAddress = createAddress(address); - - // Equals two entity created and template - Assert.assertTrue("Fields don't equals. Must be equals", equals(address, responseBodyAddress)); - deleteAddressById(responseBodyAddress.getId()); - } - - /** - * Entity must update something self fields - */ - @Test - public void updateAddress() { - Address address; - Address responseCreatedAddress; - Address responseUpdateAddress; - - address = prefillAddress(); - responseCreatedAddress = createAddress(address); - - // Change data - address.setCity("city2"); - address.setPostcode(111111); - address.setId(responseCreatedAddress.getId()); - responseUpdateAddress = updateAddress(address); - - // Created address mustn't be equals updated address - Assert.assertFalse("Fields are equals. They must be don't equals", equals(responseCreatedAddress, responseUpdateAddress)); - - // Delete entity into DB - deleteAddressById(responseUpdateAddress.getId()); - } - - @Test - public void getAllAddresses() { - List
addresses; - - addresses = new ArrayList<>(); - addresses.add(createAddress(prefillAddress())); - addresses.add(createAddress(prefillAddress())); - RestTemplate restTemplate = new RestTemplate(); - ResponseEntity> responseEntity = restTemplate.exchange( - ROOT + GET + ALL, - HttpMethod.GET, - null, - new ParameterizedTypeReference>() { - } - ); - Assert.assertEquals("Request is bad. Must be OK", "OK", responseEntity.getStatusCode().getReasonPhrase()); - Assert.assertNotNull("Not all addresses were recieve. Must be more", addresses.get(0)); - Assert.assertNotNull("Not all addresses were recieve. Must be more", addresses.get(1)); - deleteAddressById(addresses.get(0).getId()); - deleteAddressById(addresses.get(1).getId()); - } - - /** - * Create record into DB - * @param entity create entity - * @return responseBody - */ - private Address createAddress(Address entity) { - RestTemplate restTemplate; - HttpHeaders httpHeaders; - HttpEntity
httpEntity; - Address createdAddress; - - restTemplate = new RestTemplate(); - httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - httpEntity = new HttpEntity<>(entity, httpHeaders); - - createdAddress = restTemplate.exchange( - ROOT + ADD, - HttpMethod.POST, - httpEntity, - Address.class - ).getBody(); - - return createdAddress; - } - - /** - * Update record into DB - * @param entity update entity - * @return response body - */ - private Address updateAddress(Address entity) { - RestTemplate restTemplate; - HttpHeaders httpHeaders; - HttpEntity
httpEntity; - Address updateAddress; - - restTemplate = new RestTemplate(); - httpHeaders = new HttpHeaders(); - httpHeaders.setContentType(MediaType.APPLICATION_JSON_UTF8); - httpEntity = new HttpEntity<>(entity, httpHeaders); - - updateAddress = restTemplate.exchange( - ROOT + UPDATE, - HttpMethod.PUT, - httpEntity, - Address.class - ).getBody(); - - return updateAddress; - } - - /** - * Delete entity into DB by Id - * @param id - id entity - * @return response action - */ - private ResponseEntity
deleteAddressById(long id) { - RestTemplate restTemplate; - restTemplate = new RestTemplate(); - - return restTemplate.exchange( - ROOT + DELETE + ID, - HttpMethod.DELETE, - null, - Address.class, - id - ); - } - - /** - * Create and fill Address - * @return created Address - */ - private Address prefillAddress() { - - return new Address( - "region", - "city", - "street", - 105033, - "33/2", - "20", - 0.456000, - 3.123456 - ); - } - - /** - * Compare Address entity - * @param source - source entity - * @param target - equals entity - * @return is equals? - */ - private boolean equals(Address source, Address target) { - boolean isCheck = false; - - if ( - source.getCity().equals(target.getCity()) && - source.getHause().equals(target.getHause()) && - source.getLatitude() == target.getLatitude() && - source.getLongitude() == target.getLongitude() && - source.getOffice().equals(target.getOffice()) && - source.getPostcode() == target.getPostcode() && - source.getRegion().equals(target.getRegion()) && - source.getStreet().equals(target.getStreet()) - ) { - isCheck = true; - } - - - return isCheck; - } -} diff --git a/rest/src/main/java/io/khasang/ba/controller/AddressController.java b/rest/src/main/java/io/khasang/ba/controller/AddressController.java deleted file mode 100644 index 3e8cdac..0000000 --- a/rest/src/main/java/io/khasang/ba/controller/AddressController.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.khasang.ba.controller; - -import io.khasang.ba.entity.Address; -import io.khasang.ba.service.AddressService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.*; - -import java.util.List; - -@Controller -@RequestMapping(value = "/address") -public class AddressController { - @Autowired - private AddressService addressService; - - @RequestMapping(value = "/get/all", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - @ResponseBody - public List
getAll() { - return addressService.getAllAddresses(); - } - - @RequestMapping(value = "/get/{id}", method = RequestMethod.GET, produces = "application/json;charset=utf-8") - @ResponseBody - public Address getAddress(@PathVariable(value = "id") long id) { - return addressService.getAddressById(id); - } - - @RequestMapping(value = "/add", method = RequestMethod.POST, produces = "application/json;charset=utf-8") - @ResponseBody - public Address addAddress(@RequestBody Address address) { - return addressService.addAddress(address); - } - - @RequestMapping(value = "/update", method = RequestMethod.PUT, produces = "application/json;charset=utf-8") - @ResponseBody - public Address updateAddress(@RequestBody Address address) { - return addressService.updateAddress(address); - } - - @RequestMapping(value = "/delete/{id}", method = RequestMethod.DELETE, produces = "application/json;charset=utf-8") - @ResponseBody - public Address deleteAddress(@PathVariable(value = "id") long id) { - return addressService.deleteAddress(id); - } -} diff --git a/rest/src/main/java/io/khasang/ba/dao/AddressDao.java b/rest/src/main/java/io/khasang/ba/dao/AddressDao.java deleted file mode 100644 index a7ecf61..0000000 --- a/rest/src/main/java/io/khasang/ba/dao/AddressDao.java +++ /dev/null @@ -1,6 +0,0 @@ -package io.khasang.ba.dao; - -import io.khasang.ba.entity.Address; - -public interface AddressDao extends BasicDao
{ -} diff --git a/rest/src/main/java/io/khasang/ba/dao/impl/AddressDaoImpl.java b/rest/src/main/java/io/khasang/ba/dao/impl/AddressDaoImpl.java deleted file mode 100644 index e7bf56f..0000000 --- a/rest/src/main/java/io/khasang/ba/dao/impl/AddressDaoImpl.java +++ /dev/null @@ -1,10 +0,0 @@ -package io.khasang.ba.dao.impl; - -import io.khasang.ba.dao.AddressDao; -import io.khasang.ba.entity.Address; - -public class AddressDaoImpl extends BasicDaoImpl
implements AddressDao { - public AddressDaoImpl(Class
entityClass) { - super(entityClass); - } -} diff --git a/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java b/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java index e01391f..c77b767 100644 --- a/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java +++ b/rest/src/main/java/io/khasang/ba/entity/PointOfInterest.java @@ -1,11 +1,11 @@ package io.khasang.ba.entity; import com.fasterxml.jackson.annotation.JsonFormat; +import io.khasang.ba.entity.embeddable.Address; import lombok.Data; import lombok.NoArgsConstructor; -import lombok.NonNull; import org.hibernate.annotations.ColumnDefault; -import org.hibernate.validator.constraints.NotEmpty; +import org.hibernate.validator.constraints.NotBlank; import javax.persistence.*; import java.time.LocalTime; @@ -24,8 +24,7 @@ public class PointOfInterest { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @NonNull - @NotEmpty + @NotBlank private String name; @ColumnDefault(value = "'unknown'") @@ -40,6 +39,6 @@ public class PointOfInterest { @Column(name = "work_time") private Integer workTime; - @NonNull - private String address; + @Embedded + private Address address; } diff --git a/rest/src/main/java/io/khasang/ba/entity/embeddable/Address.java b/rest/src/main/java/io/khasang/ba/entity/embeddable/Address.java index 659c4d1..3eabc28 100644 --- a/rest/src/main/java/io/khasang/ba/entity/embeddable/Address.java +++ b/rest/src/main/java/io/khasang/ba/entity/embeddable/Address.java @@ -2,8 +2,8 @@ import lombok.Data; import lombok.NoArgsConstructor; -import lombok.NonNull; import org.hibernate.annotations.ColumnDefault; +import org.hibernate.validator.constraints.NotBlank; import javax.persistence.Embeddable; @@ -18,18 +18,17 @@ public class Address { private String region; - @NonNull + @NotBlank private String city; - @NonNull + @NotBlank private String street; private String postcode; - @NonNull + @NotBlank private String build; - @NonNull private String room; @ColumnDefault(value = "0.000000") diff --git a/rest/src/main/java/io/khasang/ba/service/AddressService.java b/rest/src/main/java/io/khasang/ba/service/AddressService.java deleted file mode 100644 index 754dd22..0000000 --- a/rest/src/main/java/io/khasang/ba/service/AddressService.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.khasang.ba.service; - -import io.khasang.ba.entity.Address; - -import java.util.List; - -public interface AddressService { - /** - * method for add address - * - * @param address = address for adding - * @return created address - */ - Address addAddress(Address address); - - /** - * method for getting address by specific id - * - * @param id - address - * @return address by id - */ - Address getAddressById(long id); - - /** - * method gor getting all addresses - * - * @return all addresses - */ - List
getAllAddresses(); - - /** - * method for update address - * - * @param address - address update - * @return updated address - */ - Address updateAddress(Address address); - - /** - * method for delete address by id - * - * @param id - address id for delete - * @return deleted address - */ - Address deleteAddress(long id); -} diff --git a/rest/src/main/java/io/khasang/ba/service/impl/AddressServiceImpl.java b/rest/src/main/java/io/khasang/ba/service/impl/AddressServiceImpl.java deleted file mode 100644 index fe65369..0000000 --- a/rest/src/main/java/io/khasang/ba/service/impl/AddressServiceImpl.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.khasang.ba.service.impl; - -import io.khasang.ba.dao.AddressDao; -import io.khasang.ba.entity.Address; -import io.khasang.ba.service.AddressService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.List; - -@Service -public class AddressServiceImpl implements AddressService { - @Autowired - AddressDao addressDao; - - @Override - public Address addAddress(Address address) { - return addressDao.add(address); - } - - @Override - public Address getAddressById(long id) { - return addressDao.getById(id); - } - - @Override - public List
getAllAddresses() { - return addressDao.getAll(); - } - - @Override - public Address updateAddress(Address address) { - return addressDao.update(address); - } - - @Override - public Address deleteAddress(long id) { - return addressDao.delete(this.getAddressById(id)); - } -} From a5fdffd9f532ac00a111d912b5826790c207ef11 Mon Sep 17 00:00:00 2001 From: Mozgachev Ivan Date: Tue, 28 May 2019 00:08:16 +0300 Subject: [PATCH 28/28] - delete not used package --- rest/src/main/java/io/khasang/ba/entity/Category.java | 1 - 1 file changed, 1 deletion(-) diff --git a/rest/src/main/java/io/khasang/ba/entity/Category.java b/rest/src/main/java/io/khasang/ba/entity/Category.java index 17ac718..d7ea612 100644 --- a/rest/src/main/java/io/khasang/ba/entity/Category.java +++ b/rest/src/main/java/io/khasang/ba/entity/Category.java @@ -2,7 +2,6 @@ import lombok.Data; import lombok.NoArgsConstructor; -import lombok.NonNull; import org.hibernate.annotations.NaturalId; import org.hibernate.validator.constraints.NotBlank;