RepositoryUserAccessService implements UserAccessService { @Override public User giveUserAccessUntil(User user, LocalDateTime until) throws IllegalArgumentException { if(until.isBefore(LocalDateTime.now(clock))) { throw new IllegalArgumentException("End date must lie in the future!"); } var latestIntervalOptional = user.getLatestAccessInterval(); if(latestIntervalOptional.isEmpty() || !userHasActiveAccessInterval(user)) { var interval = new AccessInterval(user, LocalDateTime.now(clock), until); user.addAccessInterval(interval); userAccessEventHandler.onAccessCreated(user, interval); return userService.save(user); } else { var latestInterval = latestIntervalOptional.get(); var oldEndTime = latestInterval.getEndTime(); if(oldEndTime.isEqual(until)) { return user; } latestInterval.setEndTime(until); intervalRepo.save(latestInterval); userAccessEventHandler.onAccessChanged(user, latestInterval, oldEndTime); } return user; } @Autowired  RepositoryUserAccessService(RepositoryUserService userService,
                                       AccessIntervalRepository intervalRepo,
                                       UserAccessEventHandler userAccessEventHandler,
                                       Clock clock); @Override User giveUserAccessUntil(User user, LocalDateTime until); @Override User removeAccessFromUser(User user); @Override boolean userHasActiveAccessInterval(User user);  }
@Test public void giveUserAccessUntilThrowsExceptionWhenTimeIsInThePast() { var endTime = LocalDateTime.now(clock).minus(1L, ChronoUnit.MINUTES); assertThatThrownBy(() -> accessService.giveUserAccessUntil(userMock, endTime)) .isInstanceOf(IllegalArgumentException.class) .hasMessage("End date must lie in the future!"); }
@Test public void giveUserAccessUntilDoesNotUpdateAccessWhenOldEndEqualsNewEnd() { var expectedStartTime = LocalDateTime.now(clock).minus(1L, ChronoUnit.DAYS); var initialEndTime = LocalDateTime.now(clock).plus(10L, ChronoUnit.MINUTES); given(userMock.getLatestAccessInterval()).willReturn(Optional.of(accessIntervalMock)); given(accessIntervalMock.getStartTime()).willReturn(expectedStartTime); given(accessIntervalMock.getEndTime()).willReturn(initialEndTime); var actualUser = accessService.giveUserAccessUntil(userMock, initialEndTime); assertThat(actualUser).isEqualTo(userMock); verify(accessIntervalMock, never()).setEndTime(any(LocalDateTime.class)); verifyZeroInteractions(intervalRepo); verifyZeroInteractions(userAccessEventHandlerMock); }
@Test public void giveUserAccessUntilSetsEndTimeWhenUserHasActiveAccess() { var expectedStartTime = LocalDateTime.now(clock).minus(1L, ChronoUnit.DAYS); var initialEndTime = LocalDateTime.now(clock).plus(10L, ChronoUnit.MINUTES); var expectedEndTime = LocalDateTime.now(clock).plus(20L, ChronoUnit.MINUTES); given(userMock.getLatestAccessInterval()).willReturn(Optional.of(accessIntervalMock)); given(accessIntervalMock.getStartTime()).willReturn(expectedStartTime); given(accessIntervalMock.getEndTime()).willReturn(initialEndTime); var actualUser = accessService.giveUserAccessUntil(userMock, expectedEndTime); assertThat(actualUser).isEqualTo(userMock);; verify(accessIntervalMock).setEndTime(expectedEndTime); verify(intervalRepo).save(accessIntervalMock); verify(userAccessEventHandlerMock).onAccessChanged(userMock, accessIntervalMock, initialEndTime); }
@Test public void giveUserAccessUntilCreatesAccessWhenUserHasNoActiveAccess() { var inactiveStartTime = LocalDateTime.now(clock).minus(10L, ChronoUnit.DAYS); var inactiveEndTime = LocalDateTime.now(clock).minus(1L, ChronoUnit.DAYS); var expectedStartTime = LocalDateTime.now(clock); var expectedEndTime = LocalDateTime.now(clock).plus(10L , ChronoUnit.DAYS); given(userMock.getLatestAccessInterval()).willReturn(Optional.of(accessIntervalMock)); given(accessIntervalMock.getStartTime()).willReturn(inactiveStartTime); given(accessIntervalMock.getEndTime()).willReturn(inactiveEndTime); given(userService.save(userMock)).willReturn(userMock); var actualUser = accessService.giveUserAccessUntil(userMock, expectedEndTime); assertThat(actualUser).isEqualTo(userMock); var captor = ArgumentCaptor.forClass(AccessInterval.class); verify(userMock, times(2)).addAccessInterval(captor.capture()); var createdAccessInterval = captor.getValue(); var softly = new SoftAssertions(); softly.assertThat(createdAccessInterval.getUser()).isEqualTo(userMock); softly.assertThat(createdAccessInterval.getStartTime()).isEqualTo(expectedStartTime); softly.assertThat(createdAccessInterval.getEndTime()).isEqualTo(expectedEndTime); softly.assertAll(); verify(userService).save(userMock); verify(userAccessEventHandlerMock).onAccessCreated(userMock, createdAccessInterval); }
@Test public void giveUserAccessUntilCreatesAccessWhenUserHasNoAccessInstance() { var expectedStartTime = LocalDateTime.now(clock); var expectedEndTime = LocalDateTime.now(clock).plus(10L , ChronoUnit.DAYS); given(userMock.getLatestAccessInterval()).willReturn(Optional.empty()); given(userService.save(userMock)).willReturn(userMock); var actualUser = accessService.giveUserAccessUntil(userMock, expectedEndTime); assertThat(actualUser).isEqualTo(userMock); var accessInfoArgumentCaptor = ArgumentCaptor.forClass(AccessInterval.class); verify(userMock, times(2)).addAccessInterval(accessInfoArgumentCaptor.capture()); var createdAccessInterval = accessInfoArgumentCaptor.getValue(); var softly = new SoftAssertions(); softly.assertThat(createdAccessInterval.getUser()).isEqualTo(userMock); softly.assertThat(createdAccessInterval.getStartTime()).isEqualTo(expectedStartTime); softly.assertThat(createdAccessInterval.getEndTime()).isEqualTo(expectedEndTime); softly.assertAll(); verify(userService).save(userMock); verify(userAccessEventHandlerMock).onAccessCreated(userMock, createdAccessInterval); }