diff --git a/src/main/java/mops/gruppen2/domain/event/AddMemberEvent.java b/src/main/java/mops/gruppen2/domain/event/AddMemberEvent.java index d638ca2..0394a0c 100644 --- a/src/main/java/mops/gruppen2/domain/event/AddMemberEvent.java +++ b/src/main/java/mops/gruppen2/domain/event/AddMemberEvent.java @@ -6,7 +6,7 @@ import lombok.Value; import lombok.extern.log4j.Log4j2; import mops.gruppen2.domain.exception.GroupFullException; import mops.gruppen2.domain.exception.IdMismatchException; -import mops.gruppen2.domain.exception.UserAlreadyExistsException; +import mops.gruppen2.domain.exception.UserExistsException; import mops.gruppen2.domain.model.group.Group; import mops.gruppen2.domain.model.group.User; import mops.gruppen2.infrastructure.GroupCache; @@ -39,7 +39,7 @@ public class AddMemberEvent extends Event { } @Override - protected void applyEvent(Group group) throws UserAlreadyExistsException, GroupFullException { + protected void applyEvent(Group group) throws UserExistsException, GroupFullException { group.addMember(target, user); log.trace("\t\t\t\t\tNeue Members: {}", group.getMembers()); diff --git a/src/main/java/mops/gruppen2/domain/exception/UserAlreadyExistsException.java b/src/main/java/mops/gruppen2/domain/exception/UserExistsException.java similarity index 68% rename from src/main/java/mops/gruppen2/domain/exception/UserAlreadyExistsException.java rename to src/main/java/mops/gruppen2/domain/exception/UserExistsException.java index d0288cd..43f5d59 100644 --- a/src/main/java/mops/gruppen2/domain/exception/UserAlreadyExistsException.java +++ b/src/main/java/mops/gruppen2/domain/exception/UserExistsException.java @@ -2,11 +2,11 @@ package mops.gruppen2.domain.exception; import org.springframework.http.HttpStatus; -public class UserAlreadyExistsException extends EventException { +public class UserExistsException extends EventException { private static final long serialVersionUID = -8150634358760194625L; - public UserAlreadyExistsException(String info) { + public UserExistsException(String info) { super(HttpStatus.INTERNAL_SERVER_ERROR, "User existiert bereits.", info); } } diff --git a/src/main/java/mops/gruppen2/domain/model/group/Group.java b/src/main/java/mops/gruppen2/domain/model/group/Group.java index 860b2a0..51dfe79 100644 --- a/src/main/java/mops/gruppen2/domain/model/group/Group.java +++ b/src/main/java/mops/gruppen2/domain/model/group/Group.java @@ -10,7 +10,7 @@ import mops.gruppen2.domain.exception.GroupFullException; import mops.gruppen2.domain.exception.IdMismatchException; import mops.gruppen2.domain.exception.LastAdminException; import mops.gruppen2.domain.exception.NoAccessException; -import mops.gruppen2.domain.exception.UserAlreadyExistsException; +import mops.gruppen2.domain.exception.UserExistsException; import mops.gruppen2.domain.exception.UserNotFoundException; import mops.gruppen2.domain.model.group.wrapper.Body; import mops.gruppen2.domain.model.group.wrapper.Description; @@ -101,7 +101,7 @@ public class Group { return memberships.get(userid).getRole(); } - public void addMember(String target, User user) throws UserAlreadyExistsException, GroupFullException { + public void addMember(String target, User user) throws UserExistsException, GroupFullException { ValidationHelper.throwIfMember(this, target); ValidationHelper.throwIfGroupFull(this); @@ -348,4 +348,8 @@ public class Group { public static Group EMPTY() { return new Group(); } + + public long getVersion() { + return meta.getVersion(); + } } diff --git a/src/main/java/mops/gruppen2/domain/model/group/GroupMeta.java b/src/main/java/mops/gruppen2/domain/model/group/GroupMeta.java index 60372dd..44a7a07 100644 --- a/src/main/java/mops/gruppen2/domain/model/group/GroupMeta.java +++ b/src/main/java/mops/gruppen2/domain/model/group/GroupMeta.java @@ -21,6 +21,9 @@ class GroupMeta { if (this.version >= version) { throw new IdMismatchException("Die Gruppe ist bereits auf einem neueren Stand."); } + if (this.version + 1 != version) { + throw new IdMismatchException("Es fehlen vorherige Events."); + } return new GroupMeta(version, creator, creationDate); } diff --git a/src/main/java/mops/gruppen2/domain/service/helper/ValidationHelper.java b/src/main/java/mops/gruppen2/domain/service/helper/ValidationHelper.java index 4e3ddd5..c82fff4 100644 --- a/src/main/java/mops/gruppen2/domain/service/helper/ValidationHelper.java +++ b/src/main/java/mops/gruppen2/domain/service/helper/ValidationHelper.java @@ -7,7 +7,7 @@ import mops.gruppen2.domain.exception.BadArgumentException; import mops.gruppen2.domain.exception.GroupFullException; import mops.gruppen2.domain.exception.LastAdminException; import mops.gruppen2.domain.exception.NoAccessException; -import mops.gruppen2.domain.exception.UserAlreadyExistsException; +import mops.gruppen2.domain.exception.UserExistsException; import mops.gruppen2.domain.exception.UserNotFoundException; import mops.gruppen2.domain.model.group.Group; import mops.gruppen2.domain.model.group.Type; @@ -39,10 +39,10 @@ public final class ValidationHelper { // ######################################## THROW ############################################ - public static void throwIfMember(Group group, String userid) throws UserAlreadyExistsException { + public static void throwIfMember(Group group, String userid) throws UserExistsException { if (group.isMember(userid)) { log.error("Benutzer {} ist schon in Gruppe {}", userid, group); - throw new UserAlreadyExistsException(userid); + throw new UserExistsException(userid); } } diff --git a/src/test/java/mops/gruppen2/domain/event/AddMemberEventTest.java b/src/test/java/mops/gruppen2/domain/event/AddMemberEventTest.java index a46f831..f2c060e 100644 --- a/src/test/java/mops/gruppen2/domain/event/AddMemberEventTest.java +++ b/src/test/java/mops/gruppen2/domain/event/AddMemberEventTest.java @@ -1,17 +1,76 @@ package mops.gruppen2.domain.event; +import mops.gruppen2.GroupBuilder; import mops.gruppen2.TestHelper; +import mops.gruppen2.domain.exception.GroupFullException; import mops.gruppen2.domain.exception.IdMismatchException; +import mops.gruppen2.domain.exception.UserExistsException; +import mops.gruppen2.domain.model.group.Group; import mops.gruppen2.domain.model.group.User; +import mops.gruppen2.domain.service.EventStoreService; +import mops.gruppen2.infrastructure.GroupCache; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; class AddMemberEventTest { + GroupCache cache; + + @BeforeEach + void setUp() { + cache = new GroupCache(mock(EventStoreService.class)); + } + @Test void userMismatch() { assertThatThrownBy(() -> new AddMemberEvent(TestHelper.uuid(1), "TEST", "TEST", new User("PETER"))) .isInstanceOf(IdMismatchException.class); } + + @Test + void apply() { + Group group = GroupBuilder.get(cache, 1).group().build(); + Event add = new AddMemberEvent(TestHelper.uuid(1), "TEST", "TEST", new User("TEST")); + add.init(2); + + add.apply(group); + + assertThat(group.getMembers()).containsExactly(new User("TEST")); + } + + @Test + void apply_cache() { + Group group = GroupBuilder.get(cache, 1).group().build(); + Event add = new AddMemberEvent(TestHelper.uuid(1), "TEST", "TEST", new User("TEST")); + add.init(2); + + add.apply(group, cache); + + assertThat(group.getMembers()).containsExactly(new User("TEST")); + assertThat(cache.userGroups("TEST")).containsExactly(group); + } + + @Test + void apply_userExists() { + Group group = GroupBuilder.get(cache, 1).group().testadmin().limit(2).build(); + Event add = new AddMemberEvent(TestHelper.uuid(1), "TEST", "TEST", new User("TEST")); + add.init(3); + + assertThatThrownBy(() -> add.apply(group, cache)) + .isInstanceOf(UserExistsException.class); + } + + @Test + void apply_groupFull() { + Group group = GroupBuilder.get(cache, 1).group().testadmin().build(); + Event add = new AddMemberEvent(TestHelper.uuid(1), "TEST", "PETER", new User("PETER")); + add.init(2); + + assertThatThrownBy(() -> add.apply(group, cache)) + .isInstanceOf(GroupFullException.class); + } } diff --git a/src/test/java/mops/gruppen2/domain/event/EventTest.java b/src/test/java/mops/gruppen2/domain/event/EventTest.java new file mode 100644 index 0000000..6998d42 --- /dev/null +++ b/src/test/java/mops/gruppen2/domain/event/EventTest.java @@ -0,0 +1,76 @@ +package mops.gruppen2.domain.event; + +import mops.gruppen2.GroupBuilder; +import mops.gruppen2.domain.exception.BadArgumentException; +import mops.gruppen2.domain.exception.IdMismatchException; +import mops.gruppen2.domain.model.group.Group; +import mops.gruppen2.domain.model.group.User; +import mops.gruppen2.infrastructure.GroupCache; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static mops.gruppen2.TestHelper.uuid; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +public class EventTest { + + @Test + void apply_smallVersion() { + Group group = GroupBuilder.get(Mockito.mock(GroupCache.class), 1).group().build(); + Event add = new AddMemberEvent(uuid(1), "TEST", "TEST", new User("TEST")); + add.init(1); + + assertThatThrownBy(() -> add.apply(group)) + .isInstanceOf(IdMismatchException.class); + } + + @Test + void apply_bigVersion() { + Group group = GroupBuilder.get(Mockito.mock(GroupCache.class), 1).group().build(); + Event add = new AddMemberEvent(uuid(1), "TEST", "TEST", new User("TEST")); + add.init(3); + + assertThatThrownBy(() -> add.apply(group)) + .isInstanceOf(IdMismatchException.class); + } + + @Test + void apply_notInitialized() { + Group group = GroupBuilder.get(Mockito.mock(GroupCache.class), 1).group().build(); + Event add = new AddMemberEvent(uuid(1), "TEST", "TEST", new User("TEST")); + + assertThatThrownBy(() -> add.apply(group)) + .isInstanceOf(BadArgumentException.class); + } + + @Test + void apply_wrongGroup() { + Group group = GroupBuilder.get(Mockito.mock(GroupCache.class), 1).group().build(); + Event add = new AddMemberEvent(uuid(2), "TEST", "TEST", new User("TEST")); + add.init(2); + + assertThatThrownBy(() -> add.apply(group)) + .isInstanceOf(IdMismatchException.class); + } + + @Test + void apply_updateVersion() { + Group group = GroupBuilder.get(Mockito.mock(GroupCache.class), 1).group().build(); + Event add = new AddMemberEvent(uuid(1), "TEST", "TEST", new User("TEST")); + add.init(2); + + assertThat(group.getVersion()).isEqualTo(1); + add.apply(group); + assertThat(group.getVersion()).isEqualTo(2); + } + + @Test + void init_alreadyInitialized() { + Event add = new AddMemberEvent(uuid(1), "TEST", "TEST", new User("TEST")); + add.init(2); + + assertThatThrownBy(() -> add.init(3)) + .isInstanceOf(BadArgumentException.class); + } +} diff --git a/src/test/java/mops/gruppen2/domain/service/GroupServiceTest.java b/src/test/java/mops/gruppen2/domain/service/GroupServiceTest.java index f0f8c7e..2effa8e 100644 --- a/src/test/java/mops/gruppen2/domain/service/GroupServiceTest.java +++ b/src/test/java/mops/gruppen2/domain/service/GroupServiceTest.java @@ -5,7 +5,7 @@ import mops.gruppen2.domain.exception.BadArgumentException; import mops.gruppen2.domain.exception.GroupFullException; import mops.gruppen2.domain.exception.LastAdminException; import mops.gruppen2.domain.exception.NoAccessException; -import mops.gruppen2.domain.exception.UserAlreadyExistsException; +import mops.gruppen2.domain.exception.UserExistsException; import mops.gruppen2.domain.exception.UserNotFoundException; import mops.gruppen2.domain.model.group.Group; import mops.gruppen2.domain.model.group.Type; @@ -137,7 +137,7 @@ class GroupServiceTest { Group group = GroupBuilder.get(mock(GroupCache.class), 1).group().testadmin().limit(3).add("PETER").build(); assertThatThrownBy(() -> groupService.addMember(group, "Test", "PETER", new User("PETER"))) - .isInstanceOf(UserAlreadyExistsException.class); + .isInstanceOf(UserExistsException.class); } @Test diff --git a/src/test/java/mops/gruppen2/domain/service/helper/ProjectionHelperTest.java b/src/test/java/mops/gruppen2/domain/service/helper/ProjectionHelperTest.java index 1d2d5b4..ced85a4 100644 --- a/src/test/java/mops/gruppen2/domain/service/helper/ProjectionHelperTest.java +++ b/src/test/java/mops/gruppen2/domain/service/helper/ProjectionHelperTest.java @@ -14,6 +14,7 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -57,7 +58,11 @@ class ProjectionHelperTest { new CreateGroupEvent(uuid(4), "TEST", LocalDateTime.now()), new CreateGroupEvent(uuid(5), "TEST", LocalDateTime.now())); - initEvents(events); + events.get(0).init(1); + events.get(1).init(1); + events.get(2).init(1); + events.get(3).init(1); + events.get(4).init(1); assertThat(project(events)).hasSize(5); } @@ -82,28 +87,40 @@ class ProjectionHelperTest { @Test void project_nocache_multipleDetailed() { - List events = Arrays.asList( + List eventsA = Arrays.asList( new CreateGroupEvent(uuid(1), "TEST", LocalDateTime.now()), new AddMemberEvent(uuid(1), "TEST", "TEST", new User("TEST")), new UpdateRoleEvent(uuid(1), "TEST", "TEST", Role.ADMIN), - new SetLimitEvent(uuid(1), "TEST", new Limit(5)), + new SetLimitEvent(uuid(1), "TEST", new Limit(5))); + List eventsB = Arrays.asList( new CreateGroupEvent(uuid(2), "TEST", LocalDateTime.now()), new AddMemberEvent(uuid(2), "TEST", "TEST", new User("TEST")), new UpdateRoleEvent(uuid(2), "TEST", "TEST", Role.ADMIN), - new SetLimitEvent(uuid(2), "TEST", new Limit(15)), + new SetLimitEvent(uuid(2), "TEST", new Limit(15))); + List eventsC = Arrays.asList( new CreateGroupEvent(uuid(3), "TEST", LocalDateTime.now()), new AddMemberEvent(uuid(3), "TEST", "TEST", new User("TEST")), new UpdateRoleEvent(uuid(3), "TEST", "TEST", Role.ADMIN), - new SetLimitEvent(uuid(3), "TEST", new Limit(25)), + new SetLimitEvent(uuid(3), "TEST", new Limit(25))); + List eventsD = Arrays.asList( new CreateGroupEvent(uuid(4), "TEST", LocalDateTime.now()), new AddMemberEvent(uuid(4), "TEST", "TEST", new User("TEST")), new UpdateRoleEvent(uuid(4), "TEST", "TEST", Role.ADMIN), new SetLimitEvent(uuid(4), "TEST", new Limit(35))); - initEvents(events); + initEvents(eventsA); + initEvents(eventsB); + initEvents(eventsC); + initEvents(eventsD); + + List events = new ArrayList<>(); + events.addAll(eventsA); + events.addAll(eventsB); + events.addAll(eventsC); + events.addAll(eventsD); List groups = project(events); @@ -156,7 +173,10 @@ class ProjectionHelperTest { new CreateGroupEvent(uuid(3), "TEST", LocalDateTime.now()), new CreateGroupEvent(uuid(4), "TEST", LocalDateTime.now())); - initEvents(events); + events.get(0).init(1); + events.get(1).init(1); + events.get(2).init(1); + events.get(3).init(1); project(groups, events, mock(GroupCache.class)); assertThat(groups).hasSize(4); @@ -166,28 +186,41 @@ class ProjectionHelperTest { @Test void project_cache_multipleDetailed() { Map groups = new HashMap<>(); - List events = Arrays.asList( + List eventsA = Arrays.asList( new CreateGroupEvent(uuid(1), "TEST", LocalDateTime.now()), new AddMemberEvent(uuid(1), "TEST", "TEST", new User("TEST")), new UpdateRoleEvent(uuid(1), "TEST", "TEST", Role.ADMIN), - new SetLimitEvent(uuid(1), "TEST", new Limit(5)), + new SetLimitEvent(uuid(1), "TEST", new Limit(5))); + List eventsB = Arrays.asList( new CreateGroupEvent(uuid(2), "TEST", LocalDateTime.now()), new AddMemberEvent(uuid(2), "TEST", "TEST", new User("TEST")), new UpdateRoleEvent(uuid(2), "TEST", "TEST", Role.ADMIN), - new SetLimitEvent(uuid(2), "TEST", new Limit(15)), + new SetLimitEvent(uuid(2), "TEST", new Limit(15))); + List eventsC = Arrays.asList( new CreateGroupEvent(uuid(3), "TEST", LocalDateTime.now()), new AddMemberEvent(uuid(3), "TEST", "TEST", new User("TEST")), new UpdateRoleEvent(uuid(3), "TEST", "TEST", Role.ADMIN), - new SetLimitEvent(uuid(3), "TEST", new Limit(25)), + new SetLimitEvent(uuid(3), "TEST", new Limit(25))); + List eventsD = Arrays.asList( new CreateGroupEvent(uuid(4), "TEST", LocalDateTime.now()), new AddMemberEvent(uuid(4), "TEST", "TEST", new User("TEST")), new UpdateRoleEvent(uuid(4), "TEST", "TEST", Role.ADMIN), new SetLimitEvent(uuid(4), "TEST", new Limit(35))); - initEvents(events); + initEvents(eventsA); + initEvents(eventsB); + initEvents(eventsC); + initEvents(eventsD); + + List events = new ArrayList<>(); + events.addAll(eventsA); + events.addAll(eventsB); + events.addAll(eventsC); + events.addAll(eventsD); + project(groups, events, mock(GroupCache.class)); assertThat(groups).hasSize(4); diff --git a/src/test/java/mops/gruppen2/infrastructure/GroupCacheTest.java b/src/test/java/mops/gruppen2/infrastructure/GroupCacheTest.java index 071289f..8031301 100644 --- a/src/test/java/mops/gruppen2/infrastructure/GroupCacheTest.java +++ b/src/test/java/mops/gruppen2/infrastructure/GroupCacheTest.java @@ -301,9 +301,9 @@ class GroupCacheTest { @Test void linksRemove() { - Group group = GroupBuilder.get(cache, 1).group().testadmin().lecture().link(1).build(); + Group group = GroupBuilder.get(cache, 1).group().testadmin().lecture().link(2).build(); - assertThat(cache.group(String.valueOf(uuid(1)))).isEqualTo(group); + assertThat(cache.group(String.valueOf(uuid(2)))).isEqualTo(group); } //Indirekt: void typesPut() {}