From 37fe08e2c6b0d399f2be909b08b1df34d93cf839 Mon Sep 17 00:00:00 2001 From: sdikyarts Date: Sat, 25 May 2024 22:49:37 +0700 Subject: [PATCH] Fix async implementation --- .../controller/AdminController.java | 27 +++++++--- .../subscriptionadmin/dto/DTOMapper.java | 17 ++++--- .../service/AdminService.java | 2 +- .../service/AdminServiceImpl.java | 30 ++++++----- src/main/resources/application-dev.properties | 2 +- .../resources/application-prod.properties | 2 +- .../resources/application-test.properties | 2 +- .../controller/AdminControllerTest.java | 51 +++++++++---------- .../service/AdminServiceImplTest.java | 42 +++++++-------- 9 files changed, 95 insertions(+), 80 deletions(-) diff --git a/src/main/java/snackscription/subscriptionadmin/controller/AdminController.java b/src/main/java/snackscription/subscriptionadmin/controller/AdminController.java index 1ab96cf..de7d02e 100644 --- a/src/main/java/snackscription/subscriptionadmin/controller/AdminController.java +++ b/src/main/java/snackscription/subscriptionadmin/controller/AdminController.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Optional; +import java.util.UUID; import java.util.concurrent.CompletableFuture; @RestController @@ -29,26 +30,38 @@ public CompletableFuture> create(@RequestBody @GetMapping("/list") public CompletableFuture>> findAll() { - return adminService.findAll().thenApply(ResponseEntity::ok) - .exceptionally(ex -> ResponseEntity.badRequest().build()); + return adminService.findAll().thenApply(ResponseEntity::ok); } @GetMapping("/{subscriptionId}") - public CompletableFuture>> findById(@PathVariable String subscriptionId) { + public CompletableFuture> findById(@PathVariable String subscriptionId) { + try { + UUID.fromString(subscriptionId); + } catch (IllegalArgumentException e) { + return CompletableFuture.completedFuture(ResponseEntity.badRequest().build()); + } return adminService.findById(subscriptionId).thenApply(ResponseEntity::ok) - .exceptionally(ex -> ResponseEntity.badRequest().build()); + .exceptionally(ex -> ResponseEntity.notFound().build()); } - @PutMapping("/update") public CompletableFuture> update(@RequestBody AdminDTO adminDTO) { + if (adminDTO.getSubscriptionId() == null) { + return CompletableFuture.completedFuture(ResponseEntity.badRequest().build()); + } + return adminService.update(adminDTO).thenApply(ResponseEntity::ok) - .exceptionally(ex -> ResponseEntity.badRequest().build()); + .exceptionally(ex -> ResponseEntity.notFound().build()); } @DeleteMapping("/{subscriptionId}") public CompletableFuture> delete(@PathVariable String subscriptionId) { - return adminService.delete(subscriptionId).thenApply(result -> ResponseEntity.ok("DELETE SUCCESS")) + try { + UUID.fromString(subscriptionId); + } catch (IllegalArgumentException e) { + return CompletableFuture.completedFuture(ResponseEntity.badRequest().build()); + } + return adminService.delete(subscriptionId).thenApply(deleted -> ResponseEntity.ok("DELETE SUCCESS")) .exceptionally(ex -> ResponseEntity.notFound().build()); } } \ No newline at end of file diff --git a/src/main/java/snackscription/subscriptionadmin/dto/DTOMapper.java b/src/main/java/snackscription/subscriptionadmin/dto/DTOMapper.java index e73a195..b81c1db 100644 --- a/src/main/java/snackscription/subscriptionadmin/dto/DTOMapper.java +++ b/src/main/java/snackscription/subscriptionadmin/dto/DTOMapper.java @@ -10,14 +10,15 @@ public class DTOMapper { public static AdminDTO convertModelToDto(AdminSubscription adminSubscription) { - return new AdminDTO( - adminSubscription.getSubscriptionId(), - adminSubscription.getUniqueCode(), - adminSubscription.getSubscriberName(), - adminSubscription.getSubscriberId(), - adminSubscription.getSubscriptionBoxId(), - adminSubscription.getSubscriptionStatus() - ); + AdminDTO adminDTO = new AdminDTO(); + adminDTO.setSubscriptionId(adminSubscription.getSubscriptionId()); + adminDTO.setSubscriptionType(adminSubscription.getSubscriptionType()); + adminDTO.setSubscriberName(adminSubscription.getSubscriberName()); + adminDTO.setSubscriberId(adminSubscription.getSubscriberId()); + adminDTO.setSubscriptionBoxId(adminSubscription.getSubscriptionBoxId()); + adminDTO.setSubscriptionStatus(adminSubscription.getSubscriptionStatus()); + adminDTO.setUniqueCode(adminSubscription.getUniqueCode()); + return adminDTO; } public static AdminSubscription convertDTOtoModel(AdminDTO adminDTO) { diff --git a/src/main/java/snackscription/subscriptionadmin/service/AdminService.java b/src/main/java/snackscription/subscriptionadmin/service/AdminService.java index 9ef4b0f..57641e7 100644 --- a/src/main/java/snackscription/subscriptionadmin/service/AdminService.java +++ b/src/main/java/snackscription/subscriptionadmin/service/AdminService.java @@ -11,7 +11,7 @@ public interface AdminService { CompletableFuture create(AdminDTO adminDTO); CompletableFuture> findAll(); - CompletableFuture> findById(String subscriptionId); + CompletableFuture findById(String subscriptionId); CompletableFuture update(AdminDTO adminDTO); CompletableFuture delete(String subscriptionId); } \ No newline at end of file diff --git a/src/main/java/snackscription/subscriptionadmin/service/AdminServiceImpl.java b/src/main/java/snackscription/subscriptionadmin/service/AdminServiceImpl.java index 319e7dc..8e4d0eb 100644 --- a/src/main/java/snackscription/subscriptionadmin/service/AdminServiceImpl.java +++ b/src/main/java/snackscription/subscriptionadmin/service/AdminServiceImpl.java @@ -8,12 +8,12 @@ import org.springframework.scheduling.annotation.Async; import java.util.List; -import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.stream.Collectors; import snackscription.subscriptionadmin.dto.DTOMapper; + @Service public class AdminServiceImpl implements AdminService{ @@ -30,23 +30,24 @@ public CompletableFuture create(AdminDTO adminDTO) { @Override @Async public CompletableFuture> findAll() { - return CompletableFuture.completedFuture(adminRepository.findAll() - .stream() + List adminSubscriptions = adminRepository.findAll(); + List adminDtos = adminSubscriptions.stream() .map(DTOMapper::convertModelToDto) - .collect(Collectors.toList())); + .collect(Collectors.toList()); + return CompletableFuture.completedFuture(adminDtos); } @Override @Async - public CompletableFuture> findById(String subscriptionId) { + public CompletableFuture findById(String subscriptionId) { if(subscriptionId == null || subscriptionId.isBlank()){ throw new IllegalArgumentException("ID cannot be null or empty"); } - AdminSubscription adminSubscription = adminRepository.findById(subscriptionId) + return adminRepository.findById(subscriptionId) + .map(DTOMapper::convertModelToDto) + .map(CompletableFuture::completedFuture) .orElseThrow(() -> new IllegalArgumentException("Subscription not found")); - - return CompletableFuture.completedFuture(Optional.of(DTOMapper.convertModelToDto(adminSubscription))); } @Override @@ -56,11 +57,11 @@ public CompletableFuture update(AdminDTO adminDTO) { throw new IllegalArgumentException("AdminDTO cannot be null"); } - AdminSubscription adminSubscription = adminRepository.findById(adminDTO.getSubscriptionId()) - .orElseThrow(() -> new IllegalArgumentException("Subscription not found")); - - DTOMapper.updateAdminSubscription(adminSubscription, adminDTO); - return CompletableFuture.completedFuture(adminRepository.update(adminSubscription)); + return adminRepository.findById(adminDTO.getSubscriptionId()). + map(adminSubscription -> { + DTOMapper.updateAdminSubscription(adminSubscription, adminDTO); + return CompletableFuture.completedFuture(adminRepository.update(adminSubscription)); + }).orElseThrow(() -> new IllegalArgumentException("Subscription not found")); } @Override @@ -70,6 +71,9 @@ public CompletableFuture delete(String subscriptionId) { throw new IllegalArgumentException("ID cannot be null or empty"); } + if (adminRepository.findById(subscriptionId).isEmpty()) { + throw new IllegalArgumentException("Subscription not found"); + } adminRepository.delete(subscriptionId); return CompletableFuture.completedFuture(null); } diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties index ffe5daf..137369d 100644 --- a/src/main/resources/application-dev.properties +++ b/src/main/resources/application-dev.properties @@ -1,4 +1,4 @@ -spring.datasource.url=jdbc:postgresql://localhost:5432/subscription-admin/ +spring.datasource.url=jdbc:postgresql://postgres:5432/subscription-admin/ spring.datasource.username=postgres spring.datasource.password=postgres spring.jpa.hibernate.ddl-auto=create-drop diff --git a/src/main/resources/application-prod.properties b/src/main/resources/application-prod.properties index 52b03e0..209fd70 100644 --- a/src/main/resources/application-prod.properties +++ b/src/main/resources/application-prod.properties @@ -1,4 +1,4 @@ -spring.datasource.url=jdbc:postgresql://aws-0-ap-southeast-1.pooler.supabase.com:5432/postgres?user=postgres.thnfvhxtvcbfxndlxdze&password=YouMakeStrayKidsStay +spring.datasource.url=jdbc:postgresql://aws-0-ap-southeast-1.pooler.supabase.com:5432/postgres spring.datasource.username=postgres.thnfvhxtvcbfxndlxdze spring.datasource.password=YouMakeStrayKidsStay spring.jpa.hibernate.ddl-auto=update diff --git a/src/main/resources/application-test.properties b/src/main/resources/application-test.properties index 0a5230d..207a451 100644 --- a/src/main/resources/application-test.properties +++ b/src/main/resources/application-test.properties @@ -1,4 +1,4 @@ -spring.datasource.url=jdbc:postgresql://postgres:5432/subscription-admin +spring.datasource.url=jdbc:postgresql://postgres:5432/subscription-admin/ spring.datasource.username=postgres spring.datasource.password=postgres spring.jpa.hibernate.ddl-auto=create diff --git a/src/test/java/snackscription/subscriptionadmin/controller/AdminControllerTest.java b/src/test/java/snackscription/subscriptionadmin/controller/AdminControllerTest.java index 20363c4..1468c42 100644 --- a/src/test/java/snackscription/subscriptionadmin/controller/AdminControllerTest.java +++ b/src/test/java/snackscription/subscriptionadmin/controller/AdminControllerTest.java @@ -1,6 +1,6 @@ package snackscription.subscriptionadmin.controller; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.*; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; @@ -28,7 +28,7 @@ public class AdminControllerTest { private AdminDTO adminDTO; private AdminSubscription adminSubscription; - @Test + @BeforeEach void setUp(){ MockitoAnnotations.openMocks(this); @@ -53,54 +53,51 @@ void setUp(){ void testCreate(){ when(adminService.create(adminDTO)).thenReturn(CompletableFuture.completedFuture(adminSubscription)); - CompletableFuture> result = adminController.create(adminDTO); - - assertNotNull(result); - assertTrue(result.isDone()); - assertEquals(ResponseEntity.ok(adminSubscription), result.join()); + CompletableFuture> response = adminController.create(adminDTO); + assertNotNull(response); + assertEquals(ResponseEntity.ok(adminSubscription), response.join()); } @Test void testFindAll(){ - when(adminService.findAll()).thenReturn(CompletableFuture.completedFuture(Collections.singletonList(adminDTO))); + List adminDTOList = Collections.singletonList(adminDTO); + when(adminService.findAll()).thenReturn(CompletableFuture.completedFuture(adminDTOList)); - CompletableFuture>> result = adminController.findAll(); - - assertNotNull(result); - assertTrue(result.isDone()); - assertEquals(ResponseEntity.ok(Collections.singletonList(adminDTO)), result.join()); + CompletableFuture>> response = adminController.findAll(); + assertNotNull(response); + assertEquals(ResponseEntity.ok(adminDTOList), response.join()); } @Test void testFindById(){ - when(adminService.findById("1")).thenReturn(CompletableFuture.completedFuture(Optional.of(adminDTO))); + String validUUID = "8a56e04b-d0c8-4e43-b2e0-fdf43e304d9e"; + adminDTO.setSubscriptionId(validUUID); + adminSubscription.setSubscriptionId(validUUID); + when(adminService.findById(validUUID)).thenReturn(CompletableFuture.completedFuture(adminDTO)); - CompletableFuture>> result = adminController.findById("1"); + CompletableFuture> result = adminController.findById(validUUID); assertNotNull(result); assertTrue(result.isDone()); - assertEquals(ResponseEntity.ok(Optional.of(adminDTO)), result.join()); + assertEquals(ResponseEntity.ok(adminDTO), result.join()); } @Test void testUpdate(){ when(adminService.update(adminDTO)).thenReturn(CompletableFuture.completedFuture(adminSubscription)); - CompletableFuture> result = adminController.update(adminDTO); - - assertNotNull(result); - assertTrue(result.isDone()); - assertEquals(ResponseEntity.ok(adminSubscription), result.join()); + CompletableFuture> response = adminController.update(adminDTO); + assertNotNull(response); + assertEquals(ResponseEntity.ok(adminSubscription), response.join()); } @Test void testDelete(){ - when(adminService.delete("1")).thenReturn(CompletableFuture.completedFuture(null)); + String validUUID = "8a56e04b-d0c8-4e43-b2e0-fdf43e304d9e"; + when(adminService.delete(validUUID)).thenReturn(CompletableFuture.completedFuture(null)); - CompletableFuture> result = adminController.delete("1"); - - assertNotNull(result); - assertTrue(result.isDone()); - assertEquals(ResponseEntity.ok("DELETE SUCCESS"), result.join()); + CompletableFuture> response = adminController.delete(validUUID); + assertNotNull(response); + assertEquals(ResponseEntity.ok("DELETE SUCCESS"), response.join()); } } diff --git a/src/test/java/snackscription/subscriptionadmin/service/AdminServiceImplTest.java b/src/test/java/snackscription/subscriptionadmin/service/AdminServiceImplTest.java index 406b58f..e96829f 100644 --- a/src/test/java/snackscription/subscriptionadmin/service/AdminServiceImplTest.java +++ b/src/test/java/snackscription/subscriptionadmin/service/AdminServiceImplTest.java @@ -5,9 +5,11 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.ResponseEntity; import snackscription.subscriptionadmin.controller.AdminController; import snackscription.subscriptionadmin.dto.AdminDTO; @@ -19,6 +21,7 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; +@ExtendWith(MockitoExtension.class) public class AdminServiceImplTest { @Mock @@ -53,13 +56,12 @@ void setUp() { adminSubscription.setSubscriberId("0325"); adminSubscription.setSubscriptionBoxId("143ily"); adminSubscription.setSubscriptionStatus("PENDING"); - - when(adminSubscriptionFactory.create(anyString(), anyString(), anyString(), anyString())).thenReturn(adminSubscription); } + @Test void testCreate() { - when(adminRepository.create(adminSubscription)).thenReturn(adminSubscription); + when(adminRepository.create(any(AdminSubscription.class))).thenReturn(adminSubscription); CompletableFuture result = adminService.create(adminDTO); @@ -70,51 +72,49 @@ void testCreate() { @Test void testFindAll() { - List adminDTOList = List.of(adminDTO); - - when(adminService.findAll()).thenReturn(CompletableFuture.completedFuture(adminDTOList)); + List adminSubscriptions = List.of(adminSubscription); + when(adminRepository.findAll()).thenReturn(adminSubscriptions); - CompletableFuture>> result = adminController.findAll(); + CompletableFuture> result = adminService.findAll(); assertNotNull(result); assertTrue(result.isDone()); - assertEquals(ResponseEntity.ok(adminDTOList), result.join()); + assertEquals(List.of(adminDTO), result.join()); } @Test void testFindById() { - Optional adminDTOOptional = Optional.of(adminDTO); + String id = "1"; + when(adminRepository.findById(id)).thenReturn(Optional.of(adminSubscription)); - when(adminRepository.findById(anyString())).thenReturn(Optional.of(adminSubscription)); - when(adminService.findById(anyString())).thenReturn(CompletableFuture.completedFuture(adminDTOOptional)); - - CompletableFuture>> result = adminController.findById("1"); + CompletableFuture result = adminService.findById(id); assertNotNull(result); assertTrue(result.isDone()); - assertEquals(ResponseEntity.ok(adminDTOOptional), result.join()); + assertEquals(adminDTO, result.join()); } @Test void testUpdate() { - when(adminService.findById(adminDTO.getSubscriptionId())).thenReturn(CompletableFuture.completedFuture(Optional.of(adminDTO))); - when(adminService.update(adminDTO)).thenReturn(CompletableFuture.completedFuture(adminSubscription)); + when(adminRepository.findById(adminDTO.getSubscriptionId())).thenReturn(Optional.of(adminSubscription)); + when(adminRepository.update(adminSubscription)).thenReturn(adminSubscription); - CompletableFuture> result = adminController.update(adminDTO); + CompletableFuture result = adminService.update(adminDTO); assertNotNull(result); assertTrue(result.isDone()); - assertEquals(ResponseEntity.ok(adminSubscription), result.join()); + assertEquals(adminSubscription, result.join()); } @Test void testDelete() { - when(adminService.delete(anyString())).thenReturn(CompletableFuture.completedFuture(null)); + String id = "1"; + when(adminRepository.findById(id)).thenReturn(Optional.of(adminSubscription)); - CompletableFuture> result = adminController.delete("1"); + CompletableFuture result = adminService.delete(id); assertNotNull(result); assertTrue(result.isDone()); - assertEquals(ResponseEntity.ok("DELETE SUCCESS"), result.join()); + assertNull(result.join()); } }