diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java index 343e08a038be9e5c6d4cebb814c54d13d6827de9..a9f57bac1d65ca9aba3af9671ab6d2efb2948558 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandRepository.java @@ -274,9 +274,10 @@ class CommandRepository { return Aggregation.newUpdate(SetOperation.set(MONGODB_STATUS).toValue(switchOperation)); } - public Command setRevokeStatusIfNotPending(String id) { - return mongoOperations.findAndModify(queryById(id), buildUpdateStatusRevokeIfNotPending(), FindAndModifyOptions.options().returnNew(true), - Command.class); + public Optional<Command> setRevokeStatusIfNotPending(String id) { + var updateCommand = mongoOperations.findAndModify(queryById(id), buildUpdateStatusRevokeIfNotPending(), + FindAndModifyOptions.options().returnNew(true), Command.class); + return Optional.ofNullable(updateCommand); } private Query queryById(String commandId) { diff --git a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java index 0f6b0783d58177fe71678e7483b74162751ef928..2f661a37b47f0da8143fdd5332e8385da4ecb1e5 100644 --- a/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java +++ b/vorgang-manager-server/src/main/java/de/ozgcloud/vorgang/command/CommandService.java @@ -24,7 +24,6 @@ package de.ozgcloud.vorgang.command; import static de.ozgcloud.vorgang.command.PersistedCommand.*; -import static java.util.Objects.*; import java.time.ZonedDateTime; import java.util.Collection; @@ -172,8 +171,8 @@ public class CommandService { publisher.publishEvent(new CommandFailedEvent(commandId, errorMessage)); } - public void revokeSubCommands(String parentId) { - repository.findSubCommandIds(parentId).forEach(this::revokeCommand); + void revokeSubCommands(String parentId) { + repository.findSubCommandIds(parentId).forEach(this::revokeCommandSilent); } public void setCommandRevoked(String commandId) { @@ -181,19 +180,21 @@ public class CommandService { } public Command revokeCommand(String commandId) { + var updatedCommand = revokeCommandSilent(commandId).orElseThrow(() -> new NotFoundException(Command.class, commandId)); + if (!isRevokePending(updatedCommand)) { + throw new RevokeFailedException(commandId, "Unexpected status '%s'. (expected: REVOKE_PENDING)".formatted(updatedCommand.getStatus())); + } + return updatedCommand; + } + + Optional<Command> revokeCommandSilent(String commandId) { var updatedCommand = repository.setRevokeStatusIfNotPending(commandId); - validateRevokeResult(updatedCommand, commandId); - publishRevokeCommandEvent(updatedCommand); + updatedCommand.filter(this::isRevokePending).ifPresent(this::publishRevokeCommandEvent); return updatedCommand; } - void validateRevokeResult(Command command, String commandId) { - if (isNull(command)) { - throw new NotFoundException(Command.class, commandId); - } - if (command.getStatus() != CommandStatus.REVOKE_PENDING) { - throw new RevokeFailedException(command.getId(), "Unexpected status '%s'. (expected: NEW or FINISHED)".formatted(command.getStatus())); - } + boolean isRevokePending(Command command) { + return command.getStatus() == CommandStatus.REVOKE_PENDING; } void publishRevokeCommandEvent(Command command) { diff --git a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java index 9023fce252fddd52337737be9588ff5a69af046e..85714d30f81e92ba77ce0c7f575e89dcc04343fa 100644 --- a/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java +++ b/vorgang-manager-server/src/test/java/de/ozgcloud/vorgang/command/CommandServiceTest.java @@ -720,66 +720,106 @@ class CommandServiceTest { @Nested class TestRevokeCommand { - final String commandId = CommandTestFactory.ID; + private static final Command REVOKE_PENDING_COMMAND = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING).build(); - @BeforeEach - void init() { - doNothing().when(service).validateRevokeResult(any(), anyString()); + @Test + void shouldCallRevokeCommandSilent() { + doReturn(Optional.of(REVOKE_PENDING_COMMAND)).when(service).revokeCommandSilent(anyString()); + + service.revokeCommand(CommandTestFactory.ID); + + verify(service).revokeCommandSilent(CommandTestFactory.ID); } @Test - void shouldCallCommandRepository() { - when(repository.setRevokeStatusIfNotPending(anyString())).thenReturn(CommandTestFactory.create()); + void shouldCallIsRevokePending() { + doReturn(Optional.of(REVOKE_PENDING_COMMAND)).when(service).revokeCommandSilent(anyString()); - service.revokeCommand(commandId); + service.revokeCommand(CommandTestFactory.ID); - verify(repository).setRevokeStatusIfNotPending(CommandTestFactory.ID); + verify(service).isRevokePending(REVOKE_PENDING_COMMAND); } @Test - void shouldCallValidateRevokeResult() { - var command = CommandTestFactory.create(); - when(repository.setRevokeStatusIfNotPending(anyString())).thenReturn(command); + void shouldReturnCommand() { + doReturn(Optional.of(REVOKE_PENDING_COMMAND)).when(service).revokeCommandSilent(anyString()); - service.revokeCommand(commandId); + var result = service.revokeCommand(CommandTestFactory.ID); - verify(service).validateRevokeResult(command, CommandTestFactory.ID); + assertThat(result).isSameAs(REVOKE_PENDING_COMMAND); } @Test - void shouldCallPublishRevokeCommandEvent() { - var command = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING).build(); - when(repository.setRevokeStatusIfNotPending(anyString())).thenReturn(command); + void shouldThrowNotFoundException() { + doReturn(Optional.empty()).when(service).revokeCommandSilent(anyString()); + + assertThrows(NotFoundException.class, () -> service.revokeCommand(CommandTestFactory.ID)); + } - service.revokeCommand(commandId); + @Test + void shouldThrowRevokeFailedException() { + doReturn(Optional.of(CommandTestFactory.create())).when(service).revokeCommandSilent(anyString()); + doReturn(false).when(service).isRevokePending(any()); - verify(service).publishRevokeCommandEvent(command); + assertThrows(RevokeFailedException.class, () -> service.revokeCommand(CommandTestFactory.ID)); + } + } + + @Nested + class TestRevokeCommandSilent { + + private static final Command COMMAND = CommandTestFactory.create(); + + @BeforeEach + void init() { + when(repository.setRevokeStatusIfNotPending(anyString())).thenReturn(Optional.of(COMMAND)); } @Test - void shouldReturnCommand() { - var command = CommandTestFactory.create(); - when(repository.setRevokeStatusIfNotPending(anyString())).thenReturn(command); + void shouldCallRepository() { + service.revokeCommandSilent(CommandTestFactory.ID); - var result = service.revokeCommand(commandId); + verify(repository).setRevokeStatusIfNotPending(CommandTestFactory.ID); + } - assertThat(result).isSameAs(command); + @Test + void shouldCallIsRevokePending() { + service.revokeCommandSilent(CommandTestFactory.ID); + + verify(service).isRevokePending(COMMAND); + } + + @Test + void shouldCallPublishRevokeCommandEvent() { + doReturn(true).when(service).isRevokePending(any()); + + service.revokeCommandSilent(CommandTestFactory.ID); + + verify(service).publishRevokeCommandEvent(COMMAND); } } @Nested - class TestValidateRevokeResult { + class TestIsRevokePending { @Test - void shouldThrowNotFoundException() { - assertThrows(NotFoundException.class, () -> service.validateRevokeResult(null, CommandTestFactory.ID)); + void shouldReturnTrue() { + var command = CommandTestFactory.createBuilder().status(CommandStatus.REVOKE_PENDING).build(); + + var result = service.isRevokePending(command); + + assertThat(result).isTrue(); } - @Test - void shouldThrowRevokeFailedException() { - var command = CommandTestFactory.create(); + @DisplayName("should return false when") + @ParameterizedTest(name = "command status is {0}") + @EnumSource(value = CommandStatus.class, names = { "REVOKE_PENDING" }, mode = EnumSource.Mode.EXCLUDE) + void shouldReturnFalse(CommandStatus status) { + var command = CommandTestFactory.createBuilder().status(status).build(); + + var result = service.isRevokePending(command); - assertThrows(RevokeFailedException.class, () -> service.validateRevokeResult(command, CommandTestFactory.ID)); + assertThat(result).isFalse(); } }