From ad186f2ea49d64c0fd9a31aa82a26b3c87e38966 Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 09:54:04 +0100 Subject: [PATCH 01/11] Unit Test for PropertiesUtil --- pom.xml | 20 +++++++++++-- .../com/dmdev/util/PropertiesUtilTest.java | 29 +++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/dmdev/util/PropertiesUtilTest.java diff --git a/pom.xml b/pom.xml index 2adffac..08d6031 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ 17 17 1.18.22 + 5.10.1 @@ -25,7 +26,7 @@ org.postgresql postgresql - 42.3.3 + 42.5.1 runtime @@ -39,13 +40,26 @@ org.junit.jupiter junit-jupiter-engine - 5.8.2 + ${junit5.version} + test + + + + org.assertj + assertj-core + 3.25.2 + test + + + org.junit.jupiter + junit-jupiter-params + ${junit5.version} test com.h2database h2 - 2.1.210 + 2.2.220 test diff --git a/src/test/java/com/dmdev/util/PropertiesUtilTest.java b/src/test/java/com/dmdev/util/PropertiesUtilTest.java new file mode 100644 index 0000000..1cb1a99 --- /dev/null +++ b/src/test/java/com/dmdev/util/PropertiesUtilTest.java @@ -0,0 +1,29 @@ +package com.dmdev.util; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.params.provider.Arguments.arguments; + +class PropertiesUtilTest { + + public static Stream propertiesProvider() { + return Stream.of( + arguments("db.url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"), + arguments("db.user", "sa"), + arguments("db.driver", "org.h2.Driver") + ); + } + + @ParameterizedTest + @MethodSource("propertiesProvider") + void whenPropertiesProvided_thenPropertiesSet(String key, String expectedValue) { + String actualValue = PropertiesUtil.get(key); + assertThat(actualValue).isEqualTo(expectedValue); + } + +} \ No newline at end of file From c506e445cbc29d77bc2dcda88623d55297cba6cb Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 11:49:58 +0100 Subject: [PATCH 02/11] Unit Test (Successful) for CreateSubscriptionValidator --- .../CreateSubscriptionValidatorTest.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java diff --git a/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java b/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java new file mode 100644 index 0000000..3cbcc34 --- /dev/null +++ b/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java @@ -0,0 +1,42 @@ +package com.dmdev.validator; + +import com.dmdev.dto.CreateSubscriptionDto; +import com.dmdev.entity.Provider; +import org.junit.jupiter.api.Test; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +import static org.assertj.core.api.Assertions.assertThat; + +class CreateSubscriptionValidatorTest { + + private static final CreateSubscriptionValidator validator = CreateSubscriptionValidator.getInstance(); + + @Test + void whenValidDto_thenValidationSuccessful() { + CreateSubscriptionDto validDto = CreateSubscriptionDto.builder() + .userId(1) + .name("Test Name") + .provider(Provider.APPLE.name()) + .expirationDate(getExpirationDate("21:00:00, 30.04.2024", "H:m:s, d.M.y")) + .build(); + + ValidationResult actualResult = validator.validate(validDto); + + assertThat(actualResult.hasErrors()).isFalse(); + + } + + private Instant getExpirationDate(String stringDate, String pattern) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern, Locale.getDefault()); + LocalDateTime localDateTime = LocalDateTime.parse(stringDate, dateTimeFormatter); + ZoneId zoneId = ZoneId.systemDefault(); + ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId); + return zonedDateTime.toInstant(); + } +} \ No newline at end of file From 8ae4a5c1fa6bbf671dd9d5c5a30f2619b86120bb Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 12:04:35 +0100 Subject: [PATCH 03/11] Unit Tests (Failing) for CreateSubscriptionValidator --- .../CreateSubscriptionValidatorTest.java | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java b/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java index 3cbcc34..7b977a9 100644 --- a/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java +++ b/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java @@ -32,6 +32,87 @@ void whenValidDto_thenValidationSuccessful() { } + @Test + void whenUserIdNull_thenValidationFails() { + CreateSubscriptionDto invalidDto = CreateSubscriptionDto.builder() + .name("Test Name") + .provider(Provider.APPLE.name()) + .expirationDate(getExpirationDate("21:00:00, 30.04.2024", "H:m:s, d.M.y")) + .build(); + + ValidationResult actualResult = validator.validate(invalidDto); + + assertThat(actualResult.hasErrors()).isTrue(); + assertThat(actualResult.getErrors().size()).isEqualTo(1); + assertThat(actualResult.getErrors().get(0).getCode()).isEqualTo(100); + assertThat(actualResult.getErrors().get(0).getMessage()).isEqualTo("userId is invalid"); + } + + @Test + void whenNameIsBlank_thenValidationFails() { + CreateSubscriptionDto invalidDto = CreateSubscriptionDto.builder() + .userId(1) + .provider(Provider.APPLE.name()) + .expirationDate(getExpirationDate("21:00:00, 30.04.2024", "H:m:s, d.M.y")) + .build(); + + ValidationResult actualResult = validator.validate(invalidDto); + + assertThat(actualResult.hasErrors()).isTrue(); + assertThat(actualResult.getErrors().size()).isEqualTo(1); + assertThat(actualResult.getErrors().get(0).getCode()).isEqualTo(101); + assertThat(actualResult.getErrors().get(0).getMessage()).isEqualTo("name is invalid"); + } + + @Test + void whenProviderIsEmpty_thenValidationFails() { + CreateSubscriptionDto invalidDto = CreateSubscriptionDto.builder() + .userId(1) + .name("Test Name") + .expirationDate(getExpirationDate("21:00:00, 30.04.2024", "H:m:s, d.M.y")) + .build(); + + ValidationResult actualResult = validator.validate(invalidDto); + + assertThat(actualResult.hasErrors()).isTrue(); + assertThat(actualResult.getErrors().size()).isEqualTo(1); + assertThat(actualResult.getErrors().get(0).getCode()).isEqualTo(102); + assertThat(actualResult.getErrors().get(0).getMessage()).isEqualTo("provider is invalid"); + } + + @Test + void whenExpirationDateIsAbsent_thenValidationFails() { + CreateSubscriptionDto invalidDto = CreateSubscriptionDto.builder() + .userId(1) + .name("Test Name") + .provider(Provider.APPLE.name()) + .build(); + + ValidationResult actualResult = validator.validate(invalidDto); + + assertThat(actualResult.hasErrors()).isTrue(); + assertThat(actualResult.getErrors().size()).isEqualTo(1); + assertThat(actualResult.getErrors().get(0).getCode()).isEqualTo(103); + assertThat(actualResult.getErrors().get(0).getMessage()).isEqualTo("expirationDate is invalid"); + } + + @Test + void whenExpirationDateIsInPast_thenValidationFails() { + CreateSubscriptionDto invalidDto = CreateSubscriptionDto.builder() + .userId(1) + .name("Test Name") + .provider(Provider.APPLE.name()) + .expirationDate(getExpirationDate("21:00:00, 30.04.2023", "H:m:s, d.M.y")) + .build(); + + ValidationResult actualResult = validator.validate(invalidDto); + + assertThat(actualResult.hasErrors()).isTrue(); + assertThat(actualResult.getErrors().size()).isEqualTo(1); + assertThat(actualResult.getErrors().get(0).getCode()).isEqualTo(103); + assertThat(actualResult.getErrors().get(0).getMessage()).isEqualTo("expirationDate is invalid"); + } + private Instant getExpirationDate(String stringDate, String pattern) { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern, Locale.getDefault()); LocalDateTime localDateTime = LocalDateTime.parse(stringDate, dateTimeFormatter); From aeb02f510164e103a76cbdaf0a1bb800230bf9dc Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 12:10:37 +0100 Subject: [PATCH 04/11] Unit Test (All fields incorrect) for CreateSubscriptionValidator --- .../CreateSubscriptionValidatorTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java b/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java index 7b977a9..1f1968a 100644 --- a/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java +++ b/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java @@ -10,6 +10,7 @@ import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Locale; +import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -113,6 +114,22 @@ void whenExpirationDateIsInPast_thenValidationFails() { assertThat(actualResult.getErrors().get(0).getMessage()).isEqualTo("expirationDate is invalid"); } + @Test + void whenAllCheckPointsFail_thenValidationFails() { + CreateSubscriptionDto invalidDto = CreateSubscriptionDto.builder() + .expirationDate(getExpirationDate("21:00:00, 30.04.2023", "H:m:s, d.M.y")) + .build(); + + ValidationResult actualResult = validator.validate(invalidDto); + + assertThat(actualResult.hasErrors()).isTrue(); + assertThat(actualResult.getErrors().size()).isEqualTo(4); + assertThat(actualResult.getErrors().stream().map(Error::getCode).collect(Collectors.toList())) + .containsExactly(100, 101, 102, 103); + assertThat(actualResult.getErrors().stream().map(Error::getMessage).collect(Collectors.toList())) + .containsExactly("userId is invalid", "name is invalid", "provider is invalid", "expirationDate is invalid"); + } + private Instant getExpirationDate(String stringDate, String pattern) { DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern, Locale.getDefault()); LocalDateTime localDateTime = LocalDateTime.parse(stringDate, dateTimeFormatter); From 99bd6d3ecfe21713d18d43dcb1cafb3cd0bbcc3c Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 12:38:34 +0100 Subject: [PATCH 05/11] Unit Test for CreateSubscriptionMapper --- .../mapper/CreateSubscriptionMapperTest.java | 39 +++++++++++++++++++ src/test/java/com/dmdev/util/DateUtil.java | 18 +++++++++ .../CreateSubscriptionValidatorTest.java | 16 +------- 3 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 src/test/java/com/dmdev/mapper/CreateSubscriptionMapperTest.java create mode 100644 src/test/java/com/dmdev/util/DateUtil.java diff --git a/src/test/java/com/dmdev/mapper/CreateSubscriptionMapperTest.java b/src/test/java/com/dmdev/mapper/CreateSubscriptionMapperTest.java new file mode 100644 index 0000000..d6104bf --- /dev/null +++ b/src/test/java/com/dmdev/mapper/CreateSubscriptionMapperTest.java @@ -0,0 +1,39 @@ +package com.dmdev.mapper; + +import com.dmdev.dto.CreateSubscriptionDto; +import com.dmdev.entity.Provider; +import com.dmdev.entity.Status; +import com.dmdev.entity.Subscription; +import org.junit.jupiter.api.Test; + +import static com.dmdev.util.DateUtil.getExpirationDate; +import static org.assertj.core.api.Assertions.assertThat; + +class CreateSubscriptionMapperTest { + + private final CreateSubscriptionMapper mapper = CreateSubscriptionMapper.getInstance(); + + @Test + void whenValidDto_thenValidSubscriptionCreated() { + String date = "21:00:00, 30.04.2024"; + String datePattern = "H:m:s, d.M.y"; + CreateSubscriptionDto validDto = CreateSubscriptionDto.builder() + .userId(1) + .name("Test Name") + .provider(Provider.GOOGLE.name()) + .expirationDate(getExpirationDate(date, datePattern)) + .build(); + + Subscription actualSub = mapper.map(validDto); + Subscription expectedSub = Subscription.builder() + .userId(1) + .name("Test Name") + .provider(Provider.GOOGLE) + .expirationDate(getExpirationDate(date, datePattern)) + .status(Status.ACTIVE) + .build(); + + assertThat(actualSub).isEqualTo(expectedSub); + + } +} \ No newline at end of file diff --git a/src/test/java/com/dmdev/util/DateUtil.java b/src/test/java/com/dmdev/util/DateUtil.java new file mode 100644 index 0000000..85934b7 --- /dev/null +++ b/src/test/java/com/dmdev/util/DateUtil.java @@ -0,0 +1,18 @@ +package com.dmdev.util; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Locale; + +public class DateUtil { + public static Instant getExpirationDate(String stringDate, String pattern) { + DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern, Locale.getDefault()); + LocalDateTime localDateTime = LocalDateTime.parse(stringDate, dateTimeFormatter); + ZoneId zoneId = ZoneId.systemDefault(); + ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId); + return zonedDateTime.toInstant(); + } +} diff --git a/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java b/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java index 1f1968a..111c3ad 100644 --- a/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java +++ b/src/test/java/com/dmdev/validator/CreateSubscriptionValidatorTest.java @@ -4,19 +4,14 @@ import com.dmdev.entity.Provider; import org.junit.jupiter.api.Test; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Locale; import java.util.stream.Collectors; +import static com.dmdev.util.DateUtil.getExpirationDate; import static org.assertj.core.api.Assertions.assertThat; class CreateSubscriptionValidatorTest { - private static final CreateSubscriptionValidator validator = CreateSubscriptionValidator.getInstance(); + private final CreateSubscriptionValidator validator = CreateSubscriptionValidator.getInstance(); @Test void whenValidDto_thenValidationSuccessful() { @@ -130,11 +125,4 @@ void whenAllCheckPointsFail_thenValidationFails() { .containsExactly("userId is invalid", "name is invalid", "provider is invalid", "expirationDate is invalid"); } - private Instant getExpirationDate(String stringDate, String pattern) { - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern, Locale.getDefault()); - LocalDateTime localDateTime = LocalDateTime.parse(stringDate, dateTimeFormatter); - ZoneId zoneId = ZoneId.systemDefault(); - ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId); - return zonedDateTime.toInstant(); - } } \ No newline at end of file From 0f70c2a994bd36a58a4a9bbf9a035da8d264cc4c Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 14:41:16 +0100 Subject: [PATCH 06/11] Unit Test with Mock stubs for SubscriptionService.upsert() - when Subscription exists --- pom.xml | 6 ++ .../service/SubscriptionServiceTest.java | 79 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/test/java/com/dmdev/service/SubscriptionServiceTest.java diff --git a/pom.xml b/pom.xml index 08d6031..ea2387a 100644 --- a/pom.xml +++ b/pom.xml @@ -62,6 +62,12 @@ 2.2.220 test + + org.mockito + mockito-junit-jupiter + 4.11.0 + test + diff --git a/src/test/java/com/dmdev/service/SubscriptionServiceTest.java b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java new file mode 100644 index 0000000..312b5af --- /dev/null +++ b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java @@ -0,0 +1,79 @@ +package com.dmdev.service; + +import com.dmdev.dao.SubscriptionDao; +import com.dmdev.dto.CreateSubscriptionDto; +import com.dmdev.entity.Provider; +import com.dmdev.entity.Status; +import com.dmdev.entity.Subscription; +import com.dmdev.mapper.CreateSubscriptionMapper; +import com.dmdev.validator.CreateSubscriptionValidator; +import com.dmdev.validator.ValidationResult; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.AdditionalAnswers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collections; + +import static com.dmdev.util.DateUtil.getExpirationDate; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class SubscriptionServiceTest { + + @Mock + private SubscriptionDao subDao; + @Mock + private CreateSubscriptionMapper createSubMapper; + @Mock + private CreateSubscriptionValidator createSubValidator; + @InjectMocks + private SubscriptionService subService; + + @Test + void whenSubscriptionExists_thenUpdateAndInsert() { + CreateSubscriptionDto dto = CreateSubscriptionDto.builder() + .userId(23) + .name("Test Name") + .provider(Provider.APPLE.name()) + .expirationDate(getExpirationDate("21:00:00, 30.04.2024", "H:m:s, d.M.y")) + .build(); + + Subscription existingSub = Subscription.builder() + .userId(23) + .name("Test Name") + .provider(Provider.APPLE) + .expirationDate(getExpirationDate("23:59:59, 31.03.2024", "H:m:s, d.M.y")) + .build(); + + Subscription updatedSub = Subscription.builder() + .userId(23) + .name("Test Name") + .provider(Provider.APPLE) + .expirationDate(dto.getExpirationDate()) + .status(Status.ACTIVE) + .build(); + + doReturn(new ValidationResult()).when(createSubValidator).validate(dto); + doReturn(Collections.singletonList(existingSub)).when(subDao).findByUserId(dto.getUserId()); + + // Ask stub DAO.upsert() method to return whichever argument it receives + when(subDao.upsert(any(Subscription.class))).then(AdditionalAnswers.returnsFirstArg()); + + assertThat(subService.upsert(dto)).isEqualTo(updatedSub); + + } + + @Test + void cancel() { + } + + @Test + void expire() { + } +} \ No newline at end of file From 62d4fdb34415e70e0eaef5d63c1b7d72fd799187 Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 15:15:56 +0100 Subject: [PATCH 07/11] Unit Test with Mock stubs for SubscriptionService.cancel() - when Active Subscription exists --- .../service/SubscriptionServiceTest.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/dmdev/service/SubscriptionServiceTest.java b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java index 312b5af..5989f2a 100644 --- a/src/test/java/com/dmdev/service/SubscriptionServiceTest.java +++ b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java @@ -16,6 +16,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import java.util.Collections; +import java.util.Optional; import static com.dmdev.util.DateUtil.getExpirationDate; import static org.assertj.core.api.Assertions.assertThat; @@ -70,7 +71,23 @@ void whenSubscriptionExists_thenUpdateAndInsert() { } @Test - void cancel() { + void whenActiveSubscriptionExists_thenCancelIt() { + Subscription existingSub = Subscription.builder() + .id(243) + .userId(23) + .name("Test Name") + .provider(Provider.APPLE) + .expirationDate(getExpirationDate("23:59:59, 31.03.2024", "H:m:s, d.M.y")) + .status(Status.ACTIVE) + .build(); + + doReturn(Optional.of(existingSub)).when(subDao).findById(any()); + // Ask stub DAO.update() method to return whichever argument it receives + when(subDao.update(any(Subscription.class))).then(AdditionalAnswers.returnsFirstArg()); + + subService.cancel(existingSub.getId()); + + assertThat(existingSub.getStatus()).isEqualTo(Status.CANCELED); } @Test From 4f5b1318574f576071d0c9da1b0dfcc6ee66c7b3 Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 15:58:47 +0100 Subject: [PATCH 08/11] Unit Test with Mock stubs for SubscriptionService.expire() - when Non Expired Subscription exists --- .../service/SubscriptionServiceTest.java | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/dmdev/service/SubscriptionServiceTest.java b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java index 5989f2a..73bb3be 100644 --- a/src/test/java/com/dmdev/service/SubscriptionServiceTest.java +++ b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java @@ -15,6 +15,9 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; import java.util.Collections; import java.util.Optional; @@ -33,8 +36,11 @@ class SubscriptionServiceTest { private CreateSubscriptionMapper createSubMapper; @Mock private CreateSubscriptionValidator createSubValidator; + @Mock + private Clock clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); + @InjectMocks - private SubscriptionService subService; + private SubscriptionService subService; // ); @Test void whenSubscriptionExists_thenUpdateAndInsert() { @@ -91,6 +97,23 @@ void whenActiveSubscriptionExists_thenCancelIt() { } @Test - void expire() { + void whenNonExpiredSubscriptionExists_thenExpireIt() { + Subscription existingSub = Subscription.builder() + .id(243) + .userId(23) + .name("Test Name") + .provider(Provider.APPLE) + .expirationDate(getExpirationDate("23:59:59, 31.03.2024", "H:m:s, d.M.y")) + .status(Status.ACTIVE) + .build(); + + doReturn(Optional.of(existingSub)).when(subDao).findById(any()); + // Ask stub DAO.update() method to return whichever argument it receives + when(subDao.update(any(Subscription.class))).then(AdditionalAnswers.returnsFirstArg()); + + subService.expire(existingSub.getId()); + + assertThat(existingSub.getStatus()).isEqualTo(Status.EXPIRED); + assertThat(existingSub.getExpirationDate()).isEqualTo(Instant.now(clock)); } } \ No newline at end of file From 2a844114029a025446d9fca5387e6b03e3d93d40 Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 16:14:44 +0100 Subject: [PATCH 09/11] verify() check added to all tests in SubscriptionServiceTest --- .../java/com/dmdev/service/SubscriptionServiceTest.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/dmdev/service/SubscriptionServiceTest.java b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java index 73bb3be..7b71c7b 100644 --- a/src/test/java/com/dmdev/service/SubscriptionServiceTest.java +++ b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java @@ -24,8 +24,7 @@ import static com.dmdev.util.DateUtil.getExpirationDate; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class SubscriptionServiceTest { @@ -73,6 +72,7 @@ void whenSubscriptionExists_thenUpdateAndInsert() { when(subDao.upsert(any(Subscription.class))).then(AdditionalAnswers.returnsFirstArg()); assertThat(subService.upsert(dto)).isEqualTo(updatedSub); + verify(subDao).upsert(existingSub); } @@ -94,6 +94,7 @@ void whenActiveSubscriptionExists_thenCancelIt() { subService.cancel(existingSub.getId()); assertThat(existingSub.getStatus()).isEqualTo(Status.CANCELED); + verify(subDao).update(existingSub); } @Test @@ -115,5 +116,6 @@ void whenNonExpiredSubscriptionExists_thenExpireIt() { assertThat(existingSub.getStatus()).isEqualTo(Status.EXPIRED); assertThat(existingSub.getExpirationDate()).isEqualTo(Instant.now(clock)); + verify(subDao).update(existingSub); } } \ No newline at end of file From 58c04558db64039a66bc10f67f221218d28f5f9e Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 16:57:30 +0100 Subject: [PATCH 10/11] assertThrows() added to some tests in SubscriptionServiceTest --- .../service/SubscriptionServiceTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/test/java/com/dmdev/service/SubscriptionServiceTest.java b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java index 7b71c7b..9db57e1 100644 --- a/src/test/java/com/dmdev/service/SubscriptionServiceTest.java +++ b/src/test/java/com/dmdev/service/SubscriptionServiceTest.java @@ -5,8 +5,11 @@ import com.dmdev.entity.Provider; import com.dmdev.entity.Status; import com.dmdev.entity.Subscription; +import com.dmdev.exception.SubscriptionException; +import com.dmdev.exception.ValidationException; import com.dmdev.mapper.CreateSubscriptionMapper; import com.dmdev.validator.CreateSubscriptionValidator; +import com.dmdev.validator.Error; import com.dmdev.validator.ValidationResult; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -23,6 +26,7 @@ import static com.dmdev.util.DateUtil.getExpirationDate; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.*; @@ -76,6 +80,17 @@ void whenSubscriptionExists_thenUpdateAndInsert() { } + @Test + void whenInvalidDto_thenExceptionThrown() { + CreateSubscriptionDto invalidDto = CreateSubscriptionDto.builder().build(); + ValidationResult invalidResult = new ValidationResult(); + invalidResult.add(Error.of(100, "userId is invalid")); + doReturn(invalidResult).when(createSubValidator).validate(invalidDto); + + assertThrows(ValidationException.class, () -> subService.upsert(invalidDto)); + verifyNoInteractions(subDao, createSubMapper); + } + @Test void whenActiveSubscriptionExists_thenCancelIt() { Subscription existingSub = Subscription.builder() @@ -97,6 +112,19 @@ void whenActiveSubscriptionExists_thenCancelIt() { verify(subDao).update(existingSub); } + @Test + void whenSubIdNotExists_thenExceptionThrown() { + doReturn(Optional.empty()).when(subDao).findById(anyInt()); + assertThrows(IllegalArgumentException.class, () -> subService.cancel(anyInt())); + } + + @Test + void whenSubIsActive_thenExceptionThrown() { + doReturn(Optional.of(Subscription.builder().status(Status.EXPIRED).build())) + .when(subDao).findById(anyInt()); + assertThrows(SubscriptionException.class, () -> subService.cancel(anyInt())); + } + @Test void whenNonExpiredSubscriptionExists_thenExpireIt() { Subscription existingSub = Subscription.builder() From 5fc6382a3aee4f3ec2be0c507cd36d607ba957c3 Mon Sep 17 00:00:00 2001 From: Andrey Agarkov Date: Tue, 6 Feb 2024 17:43:30 +0100 Subject: [PATCH 11/11] Integration tests for SubscriptionDao --- .../java/com/dmdev/dao/SubscriptionDaoIT.java | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 src/test/java/com/dmdev/dao/SubscriptionDaoIT.java diff --git a/src/test/java/com/dmdev/dao/SubscriptionDaoIT.java b/src/test/java/com/dmdev/dao/SubscriptionDaoIT.java new file mode 100644 index 0000000..3133e46 --- /dev/null +++ b/src/test/java/com/dmdev/dao/SubscriptionDaoIT.java @@ -0,0 +1,97 @@ +package com.dmdev.dao; + +import com.dmdev.entity.Provider; +import com.dmdev.entity.Status; +import com.dmdev.entity.Subscription; +import com.dmdev.integration.IntegrationTestBase; +import org.junit.jupiter.api.Test; + +import java.util.List; +import java.util.Optional; + +import static com.dmdev.util.DateUtil.getExpirationDate; +import static org.assertj.core.api.Assertions.assertThat; + +class SubscriptionDaoIT extends IntegrationTestBase { + + private final SubscriptionDao subDao = SubscriptionDao.getInstance(); + + @Test + void whenFindAll_thenAllSubsFound() { + Subscription sub1 = subDao.insert(getSubscription("User 1", 1)); + Subscription sub2 = subDao.insert(getSubscription("User 2", 2)); + Subscription sub3 = subDao.insert(getSubscription("User 3", 3)); + + List actualSub = subDao.findAll(); + List userIds = actualSub.stream().map(Subscription::getUserId).toList(); + + assertThat(userIds).containsExactly(sub1.getUserId(), sub2.getUserId(), sub3.getUserId()); + } + + @Test + void whenSubExists_thenItIsFindById() { + Subscription expectedSub = subDao.insert(getSubscription("User 1", 1)); + + Optional actualSub = subDao.findById(expectedSub.getId()); + + assertThat(actualSub).isPresent(); + assertThat(actualSub.get()).isEqualTo(expectedSub); + } + + @Test + void whenSubExists_thenItIsDeleted() { + Subscription savedSub = subDao.insert(getSubscription("User 1", 1)); + boolean isDeleted = subDao.delete(savedSub.getId()); + + assertThat(isDeleted).isTrue(); + } + + @Test + void whenSubDoesNotExist_thenItIsNotDeleted() { + subDao.insert(getSubscription("User 1", 1)); + boolean isDeleted = subDao.delete(11); + + assertThat(isDeleted).isFalse(); + } + + @Test + void update() { + Subscription insertedSub = subDao.insert(getSubscription("User 1", 1)); + insertedSub.setStatus(Status.CANCELED); + insertedSub.setExpirationDate(getExpirationDate("13:50:00, 15.03.2024", "H:m:s, d.M.y")); + subDao.update(insertedSub); + + Optional foundSub = subDao.findById(insertedSub.getId()); + + assertThat(insertedSub).isEqualTo(foundSub.get()); + + } + + @Test + void insert() { + Subscription expectedSub = getSubscription("User 1", 1); + Subscription actualSub = subDao.insert(expectedSub); + + assertThat(actualSub.getId()).isNotNull(); + } + + @Test + void findByUserId() { + Subscription expectedSub = subDao.insert(getSubscription("User 1", 1)); + + List actualSubs = subDao.findByUserId(expectedSub.getUserId()); + + assertThat(actualSubs.size()).isEqualTo(1); + assertThat(actualSubs).containsExactly(expectedSub); + } + + private Subscription getSubscription(String userName, int userId) { + return Subscription.builder() + .userId(userId) + .name(userName) + .provider(Provider.APPLE) + .expirationDate(getExpirationDate("23:59:59, 31.03.2024", "H:m:s, d.M.y")) + .status(Status.ACTIVE) + .build(); + } +} \ No newline at end of file