From e6218d05405215cde7c644f9d8a1e6c30770dd10 Mon Sep 17 00:00:00 2001 From: Marcel Lengl <52546181+LenglBoy@users.noreply.github.com> Date: Wed, 7 Feb 2018 16:24:19 +0100 Subject: [PATCH] TSK-250: CancelClaim with force-flag. --- .../main/java/pro/taskana/TaskService.java | 32 ++ .../pro/taskana/impl/TaskServiceImpl.java | 52 +++- .../acceptance/task/WorkOnTaskAccTest.java | 29 +- .../pro/taskana/impl/TaskServiceImplTest.java | 273 ++++++++++++++---- 4 files changed, 322 insertions(+), 64 deletions(-) diff --git a/lib/taskana-core/src/main/java/pro/taskana/TaskService.java b/lib/taskana-core/src/main/java/pro/taskana/TaskService.java index f8dbe8ea8..944c091d8 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/TaskService.java +++ b/lib/taskana-core/src/main/java/pro/taskana/TaskService.java @@ -56,6 +56,38 @@ public interface TaskService { Task claim(String taskId, boolean forceClaim) throws TaskNotFoundException, InvalidStateException, InvalidOwnerException; + /** + * Unclaim a existing Task which was claimed and owned by you before. + * + * @param taskId + * id of the task which should be unclaimed. + * @return updated unclaimed task + * @throws TaskNotFoundException + * if the task can´t be found or does not exist + * @throws InvalidStateException + * when the task is already completed. + * @throws InvalidOwnerException + * when the unclaim is not forced and user is diffrent. + */ + Task cancelClaim(String taskId) throws TaskNotFoundException, InvalidStateException, InvalidOwnerException; + + /** + * Unclaim a existing Task which was claimed and owned by you before. Also there can be enabled a force flag for + * admins. + * + * @param taskId + * id of the task which should be unclaimed. + * @return updated unclaimed task + * @throws TaskNotFoundException + * if the task can´t be found or does not exist + * @throws InvalidStateException + * when the task is already completed. + * @throws InvalidOwnerException + * when the unclaim is not forced and user is diffrent. + */ + Task cancelClaim(String taskId, boolean forceUnclaim) + throws TaskNotFoundException, InvalidStateException, InvalidOwnerException; + /** * Complete a claimed Task as owner/admin and update State and Timestamps. * diff --git a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java index a80ab79e2..276162745 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/impl/TaskServiceImpl.java @@ -96,11 +96,12 @@ public class TaskServiceImpl implements TaskService { taskId); throw new InvalidStateException("Task is already completed"); } - if (state == TaskState.CLAIMED && !forceClaim) { + if (state == TaskState.CLAIMED && !forceClaim && !task.getOwner().equals(userId)) { LOGGER.warn( "Method claim() found that task {} is claimed by {} and forceClaim is false. Throwing InvalidOwnerException", taskId, task.getOwner()); - throw new InvalidOwnerException("Task is already claimed by user " + task.getOwner()); + throw new InvalidOwnerException( + "You´re not the owner of this task and it is already claimed by other user " + task.getOwner()); } Instant now = Instant.now(); task.setOwner(userId); @@ -110,7 +111,6 @@ public class TaskServiceImpl implements TaskService { task.setState(TaskState.CLAIMED); taskMapper.update(task); LOGGER.debug("Method claim() claimed task '{}' for user '{}'.", taskId, userId); - } finally { taskanaEngineImpl.returnConnection(); LOGGER.debug("exit from claim()"); @@ -118,6 +118,50 @@ public class TaskServiceImpl implements TaskService { return task; } + @Override + public Task cancelClaim(String taskId) throws TaskNotFoundException, InvalidStateException, InvalidOwnerException { + return this.cancelClaim(taskId, false); + } + + @Override + public Task cancelClaim(String taskId, boolean forceUnclaim) + throws TaskNotFoundException, InvalidStateException, InvalidOwnerException { + String userId = CurrentUserContext.getUserid(); + LOGGER.debug("entry to cancelClaim(taskId = {}) with userId = {}, forceFlag = {}", taskId, userId, + forceUnclaim); + TaskImpl task = null; + try { + taskanaEngineImpl.openConnection(); + task = (TaskImpl) getTask(taskId); + TaskState state = task.getState(); + if (state == TaskState.COMPLETED) { + LOGGER.warn( + "Method cancelClaim() found that task {} is already completed. Throwing InvalidStateException", + taskId); + throw new InvalidStateException("Task is already completed"); + } + if (state == TaskState.CLAIMED && !forceUnclaim && !userId.equals(task.getOwner())) { + LOGGER.warn( + "Method cancelClaim() found that task {} is claimed by {} and forceClaim is false. Throwing InvalidOwnerException", + taskId, task.getOwner()); + throw new InvalidOwnerException("Task is already claimed by an other user = " + task.getOwner()); + } + Instant now = Instant.now(); + task.setOwner(null); + task.setModified(now); + task.setClaimed(null); + task.setRead(true); + task.setState(TaskState.READY); + taskMapper.update(task); + LOGGER.debug("Method cancelClaim() unclaimed task '{}' for user '{}'.", taskId, userId); + } finally { + taskanaEngineImpl.returnConnection(); + LOGGER.debug("exit from cancelClaim(taskId = {}) with userId = {}, forceFlag = {}", taskId, userId, + forceUnclaim); + } + return task; + } + @Override public Task completeTask(String taskId) throws TaskNotFoundException, InvalidOwnerException, InvalidStateException { @@ -139,7 +183,7 @@ public class TaskServiceImpl implements TaskService { LOGGER.warn("Method completeTask() does expect a task which need to be CLAIMED before. TaskId={}", taskId); throw new InvalidStateException(taskId); - } else if (CurrentUserContext.getUserid() != task.getOwner()) { + } else if (!CurrentUserContext.getAccessIds().contains(task.getOwner())) { LOGGER.warn( "Method completeTask() does expect to be invoced by the task-owner or a administrator. TaskId={}, TaskOwner={}, CurrentUser={}", taskId, task.getOwner(), CurrentUserContext.getUserid()); diff --git a/lib/taskana-core/src/test/java/acceptance/task/WorkOnTaskAccTest.java b/lib/taskana-core/src/test/java/acceptance/task/WorkOnTaskAccTest.java index 297471588..24abc6ee8 100644 --- a/lib/taskana-core/src/test/java/acceptance/task/WorkOnTaskAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/task/WorkOnTaskAccTest.java @@ -7,6 +7,8 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.sql.SQLException; +import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import org.h2.store.fs.FileUtils; @@ -80,7 +82,6 @@ public class WorkOnTaskAccTest extends AbstractAccTest { taskService.claim(task.getId()); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @@ -109,7 +110,6 @@ public class WorkOnTaskAccTest extends AbstractAccTest { taskService.claim(task.getId()); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @@ -121,7 +121,7 @@ public class WorkOnTaskAccTest extends AbstractAccTest { TaskService taskService = taskanaEngine.getTaskService(); Task claimedTask = taskService.getTask("TKI:000000000000000000000000000000000029"); - // taskService.cancelClaim(claimedTask.getId()); + taskService.cancelClaim(claimedTask.getId()); Task unclaimedTask = taskService.getTask("TKI:000000000000000000000000000000000029"); assertNotNull(unclaimedTask); @@ -131,7 +131,6 @@ public class WorkOnTaskAccTest extends AbstractAccTest { assertNull(unclaimedTask.getOwner()); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @@ -143,10 +142,9 @@ public class WorkOnTaskAccTest extends AbstractAccTest { TaskService taskService = taskanaEngine.getTaskService(); Task claimedTask = taskService.getTask("TKI:000000000000000000000000000000000030"); - // taskService.cancelClaim(claimedTask.getId()); + taskService.cancelClaim(claimedTask.getId()); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @@ -158,10 +156,16 @@ public class WorkOnTaskAccTest extends AbstractAccTest { TaskService taskService = taskanaEngine.getTaskService(); Task claimedTask = taskService.getTask("TKI:000000000000000000000000000000000031"); - // taskService.cancelClaim(claimedTask.getId(), true); + taskService.cancelClaim(claimedTask.getId(), true); + + Task unclaimedTask = taskService.getTask("TKI:000000000000000000000000000000000031"); + assertNotNull(unclaimedTask); + assertEquals(TaskState.READY, unclaimedTask.getState()); + assertNull(unclaimedTask.getClaimed()); + assertTrue(unclaimedTask.isRead()); + assertNull(unclaimedTask.getOwner()); } - @Ignore @WithAccessId( userName = "user_1_2", groupNames = {"group_1"}) @@ -170,6 +174,7 @@ public class WorkOnTaskAccTest extends AbstractAccTest { throws SQLException, NotAuthorizedException, InvalidArgumentException, ClassificationNotFoundException, WorkbasketNotFoundException, TaskAlreadyExistException, InvalidWorkbasketException, TaskNotFoundException, InvalidStateException, InvalidOwnerException { + Instant before = Instant.now().minus(Duration.ofSeconds(3L)); TaskService taskService = taskanaEngine.getTaskService(); Task claimedTask = taskService.getTask("TKI:000000000000000000000000000000000032"); @@ -179,7 +184,9 @@ public class WorkOnTaskAccTest extends AbstractAccTest { assertNotNull(completedTask); assertEquals(TaskState.COMPLETED, completedTask.getState()); assertNotNull(completedTask.getCompleted()); - assertEquals(completedTask.getCompleted(), claimedTask.getModified()); + assertEquals(completedTask.getCompleted(), completedTask.getModified()); + assertTrue(completedTask.getCompleted().isAfter(before)); + assertTrue(completedTask.getModified().isAfter(before)); assertTrue(completedTask.isRead()); assertEquals("user_1_2", completedTask.getOwner()); } @@ -254,7 +261,7 @@ public class WorkOnTaskAccTest extends AbstractAccTest { ConcurrencyException, AttachmentPersistenceException { TaskService taskService = taskanaEngine.getTaskService(); - ArrayList taskIdList = new ArrayList(); + ArrayList taskIdList = new ArrayList<>(); taskIdList.add("TKI:000000000000000000000000000000000100"); taskIdList.add("TKI:000000000000000000000000000000000101"); @@ -280,7 +287,7 @@ public class WorkOnTaskAccTest extends AbstractAccTest { ConcurrencyException, AttachmentPersistenceException { TaskService taskService = taskanaEngine.getTaskService(); - ArrayList taskIdList = new ArrayList(); + ArrayList taskIdList = new ArrayList<>(); taskIdList.add("TKI:000000000000000000000000000000000102"); taskIdList.add("TKI:000000000000000000000000000000000103"); taskIdList.add("TKI:000000000000000000000000000000000033"); diff --git a/lib/taskana-core/src/test/java/pro/taskana/impl/TaskServiceImplTest.java b/lib/taskana-core/src/test/java/pro/taskana/impl/TaskServiceImplTest.java index b097a31e7..08d5d70e7 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/impl/TaskServiceImplTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/impl/TaskServiceImplTest.java @@ -5,6 +5,7 @@ import static org.hamcrest.core.IsNot.not; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; @@ -37,6 +38,7 @@ import pro.taskana.Attachment; import pro.taskana.Classification; import pro.taskana.ClassificationSummary; import pro.taskana.Task; +import pro.taskana.TaskService; import pro.taskana.TaskSummary; import pro.taskana.Workbasket; import pro.taskana.WorkbasketService; @@ -67,14 +69,11 @@ import pro.taskana.security.CurrentUserContext; * * @author EH */ -// @RunWith(MockitoJUnitRunner.class) @RunWith(PowerMockRunner.class) @PrepareForTest(CurrentUserContext.class) @PowerMockIgnore("javax.management.*") public class TaskServiceImplTest { - private static final int SLEEP_TIME = 100; - @InjectMocks private TaskServiceImpl cut; @@ -344,7 +343,8 @@ public class TaskServiceImplTest { } catch (TaskAlreadyExistException ex) { verify(taskanaEngineImpl, times(1)).openConnection(); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock, classificationServiceImplMock); @@ -370,7 +370,8 @@ public class TaskServiceImplTest { verify(workbasketServiceMock, times(1)).checkAuthorization(task.getWorkbasketKey(), WorkbasketAuthorization.APPEND); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock, classificationServiceImplMock); @@ -393,7 +394,8 @@ public class TaskServiceImplTest { verify(taskanaEngineImpl, times(1)).openConnection(); verify(workbasketServiceMock, times(1)).getWorkbasketByKey(task.getWorkbasketKey()); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock, classificationServiceImplMock); @@ -401,63 +403,124 @@ public class TaskServiceImplTest { } } + @Test + public void testClaimDefaultFlag() + throws TaskNotFoundException, InvalidStateException, InvalidOwnerException { + TaskServiceImpl cutSpy = Mockito.spy(cut); + TaskImpl expectedTask = createUnitTestTask("1", "Unit Test Task 1", "1", null); + doReturn(expectedTask).when(cutSpy).claim(expectedTask.getId(), false); + cutSpy.claim(expectedTask.getId()); + verify(cutSpy, times(1)).claim(expectedTask.getId(), false); + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, + classificationQueryImplMock); + } + @Test public void testClaimSuccessfulToOwner() throws Exception { - Classification dummyClassification = createDummyClassification(); - TaskImpl expectedTask = createUnitTestTask("1", "Unit Test Task 1", "1", dummyClassification); - doReturn(null).when(attachmentMapperMock).findAttachmentsByTaskId(expectedTask.getId()); - Mockito.doReturn(expectedTask).when(taskMapperMock).findById(expectedTask.getId()); - Thread.sleep(SLEEP_TIME); // to have different timestamps + TaskServiceImpl cutSpy = Mockito.spy(cut); + TaskImpl expectedTask = createUnitTestTask("1", "Unit Test Task 1", "1", null); + Mockito.doReturn(expectedTask).when(cutSpy).getTask(expectedTask.getId()); String expectedOwner = "John Does"; + Instant before = Instant.now().minus(Duration.ofSeconds(3L)); PowerMockito.mockStatic(CurrentUserContext.class); Mockito.when(CurrentUserContext.getUserid()).thenReturn(expectedOwner); - doReturn(classificationQueryImplMock).when(classificationServiceImplMock).createClassificationQuery(); - doReturn(classificationQueryImplMock).when(classificationQueryImplMock).domainIn(any()); - doReturn(classificationQueryImplMock).when(classificationQueryImplMock).keyIn(any()); - doReturn(new ArrayList<>()).when(classificationQueryImplMock).list(); - doReturn(dummyClassification).when( - classificationServiceImplMock) - .getClassification(dummyClassification.getKey(), dummyClassification.getDomain()); - List classificationList = Arrays - .asList((ClassificationSummaryImpl) dummyClassification.asSummary()); - doReturn(classificationList).when( - classificationQueryImplMock) - .list(); + Task acturalTask = cutSpy.claim(expectedTask.getId(), true); - // Mockito.doReturn(expectedOwner).when(currentUserContext).getUserid(); - Task acturalTask = cut.claim(expectedTask.getId(), true); - - verify(taskanaEngineImpl, times(2)).openConnection(); - verify(taskMapperMock, times(1)).findById(expectedTask.getId()); - verify(attachmentMapperMock, times(1)).findAttachmentsByTaskId(expectedTask.getId()); - verify(classificationQueryImplMock, times(1)).domainIn(any()); - verify(classificationQueryImplMock, times(1)).keyIn(any()); - verify(classificationQueryImplMock, times(1)).list(); + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(cutSpy, times(1)).getTask(expectedTask.getId()); verify(taskMapperMock, times(1)).update(any()); - verify(taskanaEngineImpl, times(2)).returnConnection(); + verify(taskanaEngineImpl, times(1)).returnConnection(); verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); assertThat(acturalTask.getState(), equalTo(TaskState.CLAIMED)); assertThat(acturalTask.getCreated(), not(equalTo(expectedTask.getModified()))); - assertThat(acturalTask.getClaimed(), not(equalTo(null))); + assertTrue(acturalTask.getClaimed().isAfter(before)); + assertTrue(acturalTask.getModified().isAfter(before)); assertThat(acturalTask.getOwner(), equalTo(expectedOwner)); + assertThat(acturalTask.isRead(), equalTo(true)); } @Test(expected = TaskNotFoundException.class) public void testClaimThrowinTaskNotFoundException() throws Exception { - try { - TaskImpl expectedTask = null; - Mockito.doReturn(expectedTask).when(taskMapperMock).findById(any()); - // Mockito.doReturn("OWNER").when(currentUserContext).getUserid(); + TaskImpl expectedTask = null; + Mockito.doReturn(expectedTask).when(taskMapperMock).findById(any()); + try { cut.claim("1", true); } catch (Exception e) { verify(taskanaEngineImpl, times(2)).openConnection(); verify(taskMapperMock, times(1)).findById(any()); verify(taskanaEngineImpl, times(2)).returnConnection(); + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, + taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, + classificationQueryImplMock); + throw e; + } + } + + @Test(expected = InvalidStateException.class) + public void testClaimWithInvalidState() throws Exception { + TaskService cutSpy = Mockito.spy(cut); + TaskImpl task = createUnitTestTask("1", "taskName", "wbKey", null); + task.setState(TaskState.COMPLETED); + doReturn(task).when(cutSpy).getTask(task.getId()); + + try { + cutSpy.claim("1", true); + } catch (Exception e) { + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(cutSpy, times(1)).getTask(task.getId()); + verify(taskanaEngineImpl, times(1)).returnConnection(); + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, + taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, + classificationQueryImplMock); + throw e; + } + } + + @Test(expected = InvalidOwnerException.class) + public void testClaimWithInvalidOwner() throws Exception { + TaskService cutSpy = Mockito.spy(cut); + TaskImpl task = createUnitTestTask("1", "taskName", "wbKey", null); + task.setState(TaskState.CLAIMED); + task.setOwner("Max Mustermann"); + doReturn(task).when(cutSpy).getTask(task.getId()); + + try { + cutSpy.claim("1"); + } catch (Exception e) { + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(cutSpy, times(1)).getTask(task.getId()); + verify(taskanaEngineImpl, times(1)).returnConnection(); + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, + taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, + classificationQueryImplMock); + throw e; + } + } + + @Test(expected = InvalidStateException.class) + public void testCancelClaimForcedWithInvalidState() + throws TaskNotFoundException, + InvalidStateException, InvalidOwnerException { + TaskServiceImpl cutSpy = Mockito.spy(cut); + TaskImpl expectedTask = createUnitTestTask("1", "Unit Test Task 1", "1", null); + expectedTask.setState(TaskState.COMPLETED); + Mockito.doReturn(expectedTask).when(cutSpy).getTask(expectedTask.getId()); + + try { + cutSpy.cancelClaim(expectedTask.getId()); + } catch (InvalidStateException e) { + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(cutSpy, times(1)).getTask(expectedTask.getId()); + verify(taskanaEngineImpl, times(1)).returnConnection(); verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); @@ -465,6 +528,105 @@ public class TaskServiceImplTest { } } + @Test(expected = InvalidOwnerException.class) + public void testCancelClaimNotForcedWithInvalidOwner() + throws TaskNotFoundException, + InvalidStateException, InvalidOwnerException { + TaskServiceImpl cutSpy = Mockito.spy(cut); + TaskImpl expectedTask = createUnitTestTask("1", "Unit Test Task 1", "1", null); + expectedTask.setOwner("Thomas"); + expectedTask.setState(TaskState.CLAIMED); + Mockito.doReturn(expectedTask).when(cutSpy).getTask(expectedTask.getId()); + PowerMockito.mockStatic(CurrentUserContext.class); + Mockito.when(CurrentUserContext.getUserid()).thenReturn("Heinz"); + + try { + cutSpy.cancelClaim(expectedTask.getId()); + } catch (InvalidOwnerException e) { + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(cutSpy, times(1)).getTask(expectedTask.getId()); + verify(taskanaEngineImpl, times(1)).returnConnection(); + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, + classificationQueryImplMock); + throw e; + } + } + + @Test + public void testCancelClaimDefaultFlag() + throws TaskNotFoundException, InvalidStateException, InvalidOwnerException { + TaskServiceImpl cutSpy = Mockito.spy(cut); + TaskImpl expectedTask = createUnitTestTask("1", "Unit Test Task 1", "1", null); + doReturn(expectedTask).when(cutSpy).cancelClaim(expectedTask.getId(), false); + cutSpy.cancelClaim(expectedTask.getId()); + verify(cutSpy, times(1)).cancelClaim(expectedTask.getId(), false); + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, + classificationQueryImplMock); + } + + @Test + public void testCancelClaimSuccesfullForced() + throws TaskNotFoundException, + InvalidStateException, InvalidOwnerException { + TaskServiceImpl cutSpy = Mockito.spy(cut); + String owner = "John Does"; + TaskImpl expectedTask = createUnitTestTask("1", "Unit Test Task 1", "1", null); + expectedTask.setOwner("Some other owner"); + expectedTask.setState(TaskState.CLAIMED); + Mockito.doReturn(expectedTask).when(cutSpy).getTask(expectedTask.getId()); + Instant before = Instant.now().minus(Duration.ofSeconds(3L)); + PowerMockito.mockStatic(CurrentUserContext.class); + Mockito.when(CurrentUserContext.getUserid()).thenReturn(owner); + + Task acturalTask = cutSpy.cancelClaim(expectedTask.getId(), true); + + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(cutSpy, times(1)).getTask(expectedTask.getId()); + verify(taskMapperMock, times(1)).update(any()); + verify(taskanaEngineImpl, times(1)).returnConnection(); + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, + classificationQueryImplMock); + + assertThat(acturalTask.getState(), equalTo(TaskState.READY)); + assertThat(acturalTask.getClaimed(), equalTo(null)); + assertTrue(acturalTask.getModified().isAfter(before)); + assertThat(acturalTask.getOwner(), equalTo(null)); + assertThat(acturalTask.isRead(), equalTo(true)); + } + + @Test + public void testCancelClaimInvalidState() + throws TaskNotFoundException, InvalidStateException, InvalidOwnerException { + TaskServiceImpl cutSpy = Mockito.spy(cut); + String owner = "John Does"; + TaskImpl expectedTask = createUnitTestTask("1", "Unit Test Task 1", "1", null); + expectedTask.setOwner("Some other owner"); + expectedTask.setState(TaskState.CLAIMED); + Mockito.doReturn(expectedTask).when(cutSpy).getTask(expectedTask.getId()); + Instant before = Instant.now().minus(Duration.ofSeconds(3L)); + PowerMockito.mockStatic(CurrentUserContext.class); + Mockito.when(CurrentUserContext.getUserid()).thenReturn(owner); + + Task acturalTask = cutSpy.cancelClaim(expectedTask.getId(), true); + + verify(taskanaEngineImpl, times(1)).openConnection(); + verify(cutSpy, times(1)).getTask(expectedTask.getId()); + verify(taskMapperMock, times(1)).update(any()); + verify(taskanaEngineImpl, times(1)).returnConnection(); + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, + classificationQueryImplMock); + + assertThat(acturalTask.getState(), equalTo(TaskState.READY)); + assertThat(acturalTask.getClaimed(), equalTo(null)); + assertTrue(acturalTask.getModified().isAfter(before)); + assertThat(acturalTask.getOwner(), equalTo(null)); + assertThat(acturalTask.isRead(), equalTo(true)); + } + @Test public void testCompleteTaskDefault() throws TaskNotFoundException, InvalidOwnerException, InvalidStateException, InterruptedException, @@ -561,7 +723,8 @@ public class TaskServiceImplTest { verify(taskanaEngineImpl, times(1)).openConnection(); verify(cutSpy, times(1)).getTask(task.getId()); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); throw e; @@ -586,7 +749,8 @@ public class TaskServiceImplTest { verify(taskanaEngineImpl, times(1)).openConnection(); verify(cutSpy, times(1)).getTask(task.getId()); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); throw e; @@ -606,7 +770,8 @@ public class TaskServiceImplTest { verify(taskanaEngineImpl, times(1)).openConnection(); verify(cutSpy, times(1)).getTask(taskId); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); throw e; @@ -779,7 +944,8 @@ public class TaskServiceImplTest { verify(workbasketServiceMock, times(1)).checkAuthorization(destinationWorkbasketKey, WorkbasketAuthorization.APPEND); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); throw e; @@ -800,7 +966,8 @@ public class TaskServiceImplTest { } catch (Exception e) { verify(taskanaEngineImpl, times(1)).openConnection(); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); throw e; @@ -825,7 +992,8 @@ public class TaskServiceImplTest { verify(workbasketServiceMock, times(1)).checkAuthorization(destinationWorkbasketKey, WorkbasketAuthorization.APPEND); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); throw e; @@ -854,7 +1022,8 @@ public class TaskServiceImplTest { verify(workbasketServiceMock, times(1)).checkAuthorization(task.getWorkbasketKey(), WorkbasketAuthorization.TRANSFER); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); throw e; @@ -896,7 +1065,8 @@ public class TaskServiceImplTest { } catch (Exception e) { verify(taskanaEngineImpl, times(1)).openConnection(); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); @@ -950,7 +1120,8 @@ public class TaskServiceImplTest { verify(taskanaEngineImpl, times(1)).openConnection(); verify(taskMapperMock, times(1)).findById(task.getId()); verify(taskanaEngineImpl, times(1)).returnConnection(); - verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, taskanaEngineMock, + verifyNoMoreInteractions(attachmentMapperMock, taskanaEngineConfigurationMock, + taskanaEngineMock, taskanaEngineImpl, taskMapperMock, objectReferenceMapperMock, workbasketServiceMock, sqlSessionMock, classificationQueryImplMock); throw e; @@ -1060,7 +1231,8 @@ public class TaskServiceImplTest { verify(taskMapperMock, times(1)).findTaskSummariesByWorkbasketKey(workbasketKey); verify(taskanaEngineImpl, times(1)).returnConnection(); verify(workbasketServiceMock, times(1)).getWorkbasketByKey(any()); - verifyNoMoreInteractions(attachmentMapperMock, taskMapperMock, taskanaEngineImpl, workbasketServiceMock); + verifyNoMoreInteractions(attachmentMapperMock, taskMapperMock, taskanaEngineImpl, + workbasketServiceMock); assertThat(actualResultList, equalTo(expectedResultList)); assertThat(actualResultList.size(), equalTo(expectedResultList.size())); @@ -1227,9 +1399,12 @@ public class TaskServiceImplTest { task.setWorkbasketKey(workbasketKey); task.setDomain(""); task.setAttachments(new ArrayList<>()); - Instant now = Instant.now(); + Instant now = Instant.now().minus(Duration.ofMinutes(1L)); task.setCreated(now); task.setModified(now); + if (classification == null) { + classification = createDummyClassification(); + } task.setClassificationSummary(classification.asSummary()); task.setClassificationKey(classification.getKey()); task.setDomain(classification.getDomain());