diff --git a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/SubscriptionRepository.java b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/repository/SubscriptionRepository.java similarity index 96% rename from src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/SubscriptionRepository.java rename to src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/repository/SubscriptionRepository.java index ddd126a..d3c16c5 100644 --- a/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/SubscriptionRepository.java +++ b/src/main/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/repository/SubscriptionRepository.java @@ -1,4 +1,4 @@ -package fr.iut_fbleau.but3.dev62.mylibrary.subscription; +package fr.iut_fbleau.but3.dev62.mylibrary.subscription.repository; import fr.iut_fbleau.but3.dev62.mylibrary.subscription.entity.Subscription; diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/exception/SubscriptionNotFoundExceptionTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/exception/SubscriptionNotFoundExceptionTest.java new file mode 100644 index 0000000..566d811 --- /dev/null +++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/exception/SubscriptionNotFoundExceptionTest.java @@ -0,0 +1,74 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.subscription.exception; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.Optional; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class SubscriptionNotFoundExceptionTest { + + @Test + @DisplayName("Exception message should contain the UUID provided for customer") + void testExceptionMessageContainsUUIDForCustomer() { + UUID customerUUID = UUID.randomUUID(); + + SubscriptionNotFoundException exception = new SubscriptionNotFoundException(Optional.of(customerUUID), Optional.empty()); + + String expectedMessage = String.format("The subscriptions with the customer id %s does not exists", customerUUID); + assertEquals(expectedMessage, exception.getMessage()); + } + + @Test + @DisplayName("Exception message should contain the UUID provided for subscription") + void testExceptionMessageContainsUUIDForSubscription() { + UUID subscriptionUUID = UUID.randomUUID(); + + SubscriptionNotFoundException exception = new SubscriptionNotFoundException(Optional.empty(), Optional.of(subscriptionUUID)); + + String expectedMessage = String.format("The review with subscription id %s does not exists", subscriptionUUID); + assertEquals(expectedMessage, exception.getMessage()); + } + + @Test + @DisplayName("Exception should use the correct constant message format for customer") + void testExceptionUsesConstantMessageCustomerFormat() { + UUID customerUUID = UUID.randomUUID(); + + SubscriptionNotFoundException exception = new SubscriptionNotFoundException(Optional.of(customerUUID), Optional.empty()); + + String expectedFormatWithPlaceholder = "The subscriptions with the customer id {0} does not exists"; + assertEquals(SubscriptionNotFoundException.THE_SUBSCRIPTION_WITH_CUSTOMER_ID_DOES_NOT_EXIST_MESSAGE, + expectedFormatWithPlaceholder); + assertTrue(exception.getMessage().contains(customerUUID.toString())); + } + + @Test + @DisplayName("Exception should use the correct constant message format for subscription") + void testExceptionUsesConstantMessageSubscriptionFormat() { + UUID subscriptionUUID = UUID.randomUUID(); + + SubscriptionNotFoundException exception = new SubscriptionNotFoundException(Optional.empty(), Optional.of(subscriptionUUID)); + + String expectedFormatWithPlaceholder = "The subscription with subscription id {0} does not exists"; + assertEquals(SubscriptionNotFoundException.THE_SUBSCRIPTION_WITH_SUBSCRIPTION_ID_DOES_NOT_EXIST_MESSAGE, + expectedFormatWithPlaceholder); + assertTrue(exception.getMessage().contains(subscriptionUUID.toString())); + } + + @Test + @DisplayName("Exception should be properly thrown and caught") + void testExceptionCanBeThrownAndCaught() { + UUID subscriptionUUID = UUID.randomUUID(); + + try { + throw new SubscriptionNotFoundException(Optional.empty(), Optional.of(subscriptionUUID)); + } catch (SubscriptionNotFoundException e) { + String expectedMessage = String.format("The subscription with subscription id %s does not exists", subscriptionUUID); + assertEquals(expectedMessage, e.getMessage()); + } + } +} diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/repository/SubscriptionRepositoryTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/repository/SubscriptionRepositoryTest.java index 3904bcc..1f3d4fd 100644 --- a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/repository/SubscriptionRepositoryTest.java +++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/repository/SubscriptionRepositoryTest.java @@ -2,7 +2,6 @@ package fr.iut_fbleau.but3.dev62.mylibrary.subscription.repository; import fr.iut_fbleau.but3.dev62.mylibrary.subscription.DesiredSubscriptionDuration; import fr.iut_fbleau.but3.dev62.mylibrary.subscription.PaymentType; -import fr.iut_fbleau.but3.dev62.mylibrary.subscription.SubscriptionRepository; import fr.iut_fbleau.but3.dev62.mylibrary.subscription.entity.PaymentMethod; import fr.iut_fbleau.but3.dev62.mylibrary.subscription.entity.Subscription; import org.junit.jupiter.api.BeforeEach; diff --git a/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/usecase/SubscriptionUseCaseTest.java b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/usecase/SubscriptionUseCaseTest.java new file mode 100644 index 0000000..964ce6e --- /dev/null +++ b/src/test/java/fr/iut_fbleau/but3/dev62/mylibrary/subscription/usecase/SubscriptionUseCaseTest.java @@ -0,0 +1,269 @@ +package fr.iut_fbleau.but3.dev62.mylibrary.subscription.usecase; + +import fr.iut_fbleau.but3.dev62.mylibrary.review.exception.NotValidReviewException; +import fr.iut_fbleau.but3.dev62.mylibrary.review.exception.ReviewNotFoundException; +import fr.iut_fbleau.but3.dev62.mylibrary.subscription.*; +import fr.iut_fbleau.but3.dev62.mylibrary.subscription.entity.PaymentMethod; +import fr.iut_fbleau.but3.dev62.mylibrary.subscription.entity.Subscription; +import fr.iut_fbleau.but3.dev62.mylibrary.subscription.exception.NotValidSubscriptionException; +import fr.iut_fbleau.but3.dev62.mylibrary.subscription.repository.SubscriptionRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.*; +import static org.mockito.Mockito.never; + +@ExtendWith(MockitoExtension.class) +public class SubscriptionUseCaseTest { + + @Mock + private SubscriptionRepository subscriptionRepository; + + @InjectMocks + private SubscriptionUseCase subscriptionUseCase; + + private UUID subscriptionId; + private UUID customerId; + private Integer desiredSubscriptionDuration; + private PaymentMethod paymentMethod; + private LocalDate desiredStartDate; + private double monthlyAmount; + private Subscription testSubscription; + private SubscriptionInfo validSubscriptionInfo; + + @BeforeEach + void setUp() { + subscriptionId = UUID.randomUUID(); + customerId = UUID.randomUUID(); + desiredSubscriptionDuration = DesiredSubscriptionDuration.THREE.getValue(); + desiredStartDate = LocalDate.of(2026, 6, 24); + paymentMethod = PaymentMethod.builder() + .paymentType(PaymentType.CB.name()) + .details("Maxime Lebreton") + .build(); + monthlyAmount = 12.99; + + testSubscription = Subscription.builder() + .subscriptionId(subscriptionId) + .customerId(customerId) + .desiredSubscriptionDuration(desiredSubscriptionDuration) + .paymentMethod(paymentMethod) + .desiredStartDate(desiredStartDate) + .monthlyAmount(monthlyAmount) + .build(); + + validSubscriptionInfo = new SubscriptionInfo(desiredSubscriptionDuration, desiredStartDate); + } + + @Nested + @DisplayName("Register subscription tests") + class RegisterSubscriptionTests { + + @Test + @DisplayName("Should register review when valid data is provided") + void testRegisterSubscriptionithValidData() throws NotValidSubscriptionException { + when(subscriptionRepository.save(any(Subscription.class))).thenReturn(testSubscription); + + UUID registeredId = subscriptionUseCase.registerSubscription(validSubscriptionInfo); + + assertNotNull(registeredId); + assertEquals(subscriptionId, registeredId); + verify(subscriptionRepository, times(1)).save(any(Subscription.class)); + } + + @Test + @DisplayName("Should throw exception when review data is not valid") + void testRegisterSubscriptionWithInvalidData() { + SubscriptionInfo invalidSubscriptionInfo = new SubscriptionInfo(0, desiredStartDate); + + assertThrows(NotValidSubscriptionException.class, + () -> subscriptionUseCase.registerSubscription(invalidSubscriptionInfo)); + + verify(subscriptionRepository, never()).save(any(Subscription.class)); + } + } + + @Nested + @DisplayName("Find subscription tests") + class FindSubscriptionTests { + + @Test + @DisplayName("Should return reviews when customer ID exists") + void testFindSubscriptionByCustomerId() { + when(subscriptionRepository.FindByCustomerId(customerId)).thenReturn(List.of(testSubscription)); + + List foundSubscriptions = subscriptionUseCase.findReviewByCustomerId(customerId); + + assertFalse(foundSubscriptions.isEmpty()); + boolean allSameCustomer = foundSubscriptions.stream() + .allMatch(review -> review.getCustomerId().equals(customerId)); + assertTrue(allSameCustomer); + verify(subscriptionRepository, times(1)).FindByCustomerId(customerId); + } + + @Test + @DisplayName("Should return empty Optional when customer ID doesn't exist") + void testFindSubscriptionByCustomerIdNotFound() { + UUID nonExistentCustomerId = UUID.randomUUID(); + when(subscriptionRepository.FindByCustomerId(nonExistentCustomerId)).thenReturn(List.of()); + + List foundSubscriptions = subscriptionUseCase.findReviewByCustomerId(nonExistentCustomerId); + + assertTrue(foundSubscriptions.isEmpty()); + verify(subscriptionRepository, times(1)).FindByCustomerId(nonExistentCustomerId); + } + + @Test + @DisplayName("Should return review when Subscription ID exists") + void testFindSubscriptionBySubscriptionId() { + when(subscriptionRepository.findBySubscriptionId(subscriptionId)).thenReturn(Optional.of(testSubscription)); + + Optional foundSubscription = subscriptionUseCase.findReviewBySubscriptionId(subscriptionId); + + assertTrue(foundSubscription.isPresent()); + assertEquals(testSubscription.getCustomerId(), foundSubscription.get().getCustomerId()); + assertEquals(testSubscription.getMonthlyAmount(), foundSubscription.get().getMonthlyAmount()); + verify(subscriptionRepository, times(1)).findBySubscriptionId(subscriptionId); + } + + @Test + @DisplayName("Should return empty Optional when review ID doesn't exist") + void testFindSubscriptionBySubscriptionIdNotFound() { + UUID nonExistentSubscriptionId = UUID.randomUUID(); + when(subscriptionRepository.findBySubscriptionId(nonExistentSubscriptionId)).thenReturn(Optional.empty()); + + Optional foundSubscription = subscriptionUseCase.findSubscriptionByReviewId(nonExistentSubscriptionId); + + assertTrue(foundSubscription.isEmpty()); + verify(subscriptionRepository, times(1)).findBySubscriptionId(nonExistentSubscriptionId); + } + } + + @Nested + @DisplayName("Update subscription tests") + class UpdateSubscriptionTests { + + @Test + @DisplayName("Should update subscription when valid data is provided") + void testUpdateSubscriptionWithValidData() throws SubscriptionNotFoundException, NotValidReviewException { + when(subscriptionRepository.findBySubscriptionId(subscriptionId)).thenReturn(Optional.of(testSubscription)); + + LocalDate updateDdesiredStartDate = LocalDate.of(2026, 6, 24); + Subscription updatedSubscription = Subscription.builder() + .subscriptionId(subscriptionId) + .customerId(customerId) + .desiredSubscriptionDuration(desiredSubscriptionDuration) + .paymentMethod(paymentMethod) + .desiredStartDate(desiredStartDate) + .monthlyAmount(monthlyAmount) + .build(); + + when(subscriptionRepository.save(any(Subscription.class))).thenReturn(updatedSubscription); + + SubscriptionInfo updateInfo = new SubscriptionInfo(DesiredSubscriptionDuration.SIX.getValue(), updateDdesiredStartDate); + + SubscriptionDTO result = subscriptionUseCase.updateSubscription(subscriptionId, updateInfo, paymentMethod); + + assertNotNull(result); + assertEquals(customerId, result.getCustomerId()); + assertEquals(monthlyAmount, result.getMonthlyAmount()); + verify(subscriptionRepository, times(1)).findBySubscriptionId(subscriptionId); + verify(subscriptionRepository, times(1)).save(any(Subscription.class)); + } + + @Test + @DisplayName("Should throw exception when subscription ID doesn't exist") + void testUpdateSubscriptionNotFound() { + UUID nonExistentSubscriptionId = UUID.randomUUID(); + when(subscriptionRepository.findBySubscriptionId(nonExistentSubscriptionId)).thenReturn(Optional.empty()); + + SubscriptionInfo updateInfo = new SubscriptionInfo(desiredSubscriptionDuration, desiredStartDate); + + assertThrows(SubscriptionNotFoundException.class, + () -> subscriptionUseCase.updateSubscription(nonExistentSubscriptionId, updateInfo, paymentMethod)); + + verify(subscriptionRepository, times(1)).findBySubscriptionId(nonExistentSubscriptionId); + verify(subscriptionRepository, never()).save(any(Subscription.class)); + } + + @Test + @DisplayName("Should throw exception when update data is not valid") + void testUpdateSubscriptionWithInvalidData() { + SubscriptionInfo invalidUpdateInfo = new SubscriptionInfo(0, desiredStartDate); + + assertThrows(NotValidSubscriptionException.class, + () -> subscriptionUseCase.updateSubscription(subscriptionId, invalidUpdateInfo, paymentMethod)); + + verify(subscriptionRepository, never()).findBySubscriptionId(any(UUID.class)); + verify(subscriptionRepository, never()).save(any(Subscription.class)); + } + } + + @Nested + @DisplayName("Delete subscription tests") + class DeleteReviewTests { + + @Test + @DisplayName("Should delete subscriptions when customer ID exists") + void testDeleteSubscriptionsOfACustomer() throws SubscriptionNotFoundException { + when(subscriptionRepository.FindByCustomerId(customerId)).thenReturn(List.of(testSubscription)); + doNothing().when(subscriptionRepository).delete(testSubscription); + + subscriptionUseCase.deleteSubscriptionsOfACustomer(customerId); + + verify(subscriptionRepository, times(1)).FindByCustomerId(customerId); + verify(subscriptionRepository, times(1)).delete(testSubscription); + } + + @Test + @DisplayName("Should throw exception when customer ID doesn't exist") + void testDeleteSubscriptionsOfACustomerNotFound() { + UUID nonExistentCustomerId = UUID.randomUUID(); + when(subscriptionRepository.FindByCustomerId(nonExistentCustomerId)).thenReturn(List.of()); + + assertThrows(ReviewNotFoundException.class, + () -> subscriptionUseCase.deleteSubscriptionsOfACustomer(nonExistentCustomerId)); + + verify(subscriptionRepository, times(1)).FindByCustomerId(nonExistentCustomerId); + verify(subscriptionRepository, never()).delete(any(Subscription.class)); + } + + @Test + @DisplayName("Should delete subscription when subscription ID exist") + void testDeleteSubscription() throws SubscriptionNotFoundException { + when(subscriptionRepository.findBySubscriptionId(subscriptionId)).thenReturn(Optional.of(testSubscription)); + doNothing().when(subscriptionRepository).delete(testSubscription); + + subscriptionUseCase.deleteSubscription(subscriptionId); + + verify(subscriptionRepository, times(1)).findBySubscriptionId(subscriptionId); + verify(subscriptionRepository, times(1)).delete(testSubscription); + } + + @Test + @DisplayName("Should throw exception when subscription ID doesn't exist") + void testDeleteSubscriptionNotFound() { + UUID nonExistentSubscriptionId = UUID.randomUUID(); + when(subscriptionRepository.findBySubscriptionId(nonExistentSubscriptionId)).thenReturn(Optional.empty()); + + assertThrows(ReviewNotFoundException.class, + () -> subscriptionUseCase.deleteSubscription(nonExistentSubscriptionId)); + + verify(subscriptionRepository, times(1)).findBySubscriptionId(nonExistentSubscriptionId); + verify(subscriptionRepository, never()).delete(any(Subscription.class)); + } + } +}