-
Notifications
You must be signed in to change notification settings - Fork 35
HomeWork solution #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: homework
Are you sure you want to change the base?
Changes from all commits
ad186f2
c506e44
8ae4a5c
aeb02f5
99bd6d3
0f70c2a
62d4fdb
4f5b131
2a84411
58c0455
5fc6382
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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(); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Лучше использовать общепринятые сокращения в именовании всего в Java (sub). |
||
|
|
||
| @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<Subscription> actualSub = subDao.findAll(); | ||
| List<Integer> userIds = actualSub.stream().map(Subscription::getUserId).toList(); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. разделяй четко 3 секции в тесте, чтобы улучшить его читабильность: given/when/then |
||
|
|
||
| assertThat(userIds).containsExactly(sub1.getUserId(), sub2.getUserId(), sub3.getUserId()); | ||
| } | ||
|
|
||
| @Test | ||
| void whenSubExists_thenItIsFindById() { | ||
| Subscription expectedSub = subDao.insert(getSubscription("User 1", 1)); | ||
|
|
||
| Optional<Subscription> 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()); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is* больше относится к именованию методов, а не локальных переменных |
||
|
|
||
| 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<Subscription> 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<Subscription> actualSubs = subDao.findByUserId(expectedSub.getUserId()); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Для теста метода findByUserId нужна вставить несколько подписок с разным userId - иначе некорректный dataset. Его можно заменить на findAll, например, и он все еще будет проходить |
||
|
|
||
| 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(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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); | ||
|
|
||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не надо оставлять пустые строки в конце метода |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| 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.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; | ||
| import org.mockito.AdditionalAnswers; | ||
| import org.mockito.InjectMocks; | ||
| 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; | ||
|
|
||
| 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.*; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Подправь в настройках idea, чтобы не схлопывало импорты в * |
||
|
|
||
| @ExtendWith(MockitoExtension.class) | ||
| class SubscriptionServiceTest { | ||
|
|
||
| @Mock | ||
| private SubscriptionDao subDao; | ||
| @Mock | ||
| private CreateSubscriptionMapper createSubMapper; | ||
| @Mock | ||
| private CreateSubscriptionValidator createSubValidator; | ||
| @Mock | ||
| private Clock clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. это не мок |
||
|
|
||
| @InjectMocks | ||
| private SubscriptionService subService; // ); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не оставляй закоментированного кода |
||
|
|
||
| @Test | ||
| void whenSubscriptionExists_thenUpdateAndInsert() { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. не может сразу и обновить и вставить метод |
||
| 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); | ||
| verify(subDao).upsert(existingSub); | ||
|
|
||
| } | ||
|
|
||
| @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() | ||
| .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); | ||
| 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())); | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нужно проверить какое именно исключение упало, например, код/текст исключения и т.д. Иначе причина может поменяться, а тест будет проходить |
||
| } | ||
|
|
||
| @Test | ||
| 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)); | ||
| verify(subDao).update(existingSub); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. если это утилитный класс - то final класс и private консторуктор |
||
| 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(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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<Arguments> 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); | ||
| } | ||
|
|
||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
а не должен совпадать с junit 5 версией?