package ru.hflabs.rcd.task; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.mockito.internal.verification.Times; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.springframework.context.ApplicationEventPublisher; import org.testng.annotations.*; import ru.hflabs.rcd.event.task.TaskEvent; import ru.hflabs.rcd.event.task.TaskExecutionEvent; import ru.hflabs.rcd.event.task.TaskProgressEvent; import ru.hflabs.rcd.model.task.*; import ru.hflabs.rcd.service.task.ITaskPerformer; import ru.hflabs.rcd.service.task.ITaskProgress; import java.util.Collections; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import static org.testng.Assert.*; import static ru.hflabs.rcd.model.MockFactory.createMockTaskDescriptor; @Test public class TaskWorkerTest { /** Пул выполнения задач */ private ExecutorService executorService; /** Сервис выполнения задач */ private ITaskPerformer performer; /** Сервис публикации событий */ private ApplicationEventPublisher eventPublisher; @BeforeClass private void createExecutorService() { executorService = Executors.newSingleThreadExecutor(); performer = Mockito.mock(ITaskPerformer.class); eventPublisher = Mockito.mock(ApplicationEventPublisher.class); } @AfterClass private void disposeExecutorService() { executorService.shutdownNow(); performer = null; eventPublisher = null; } @BeforeMethod @AfterMethod private void purgeMocks() { Mockito.reset(performer, eventPublisher); } private static void assertTaskProgressEvent(TaskEvent actual, TaskProgressEvent expected) { assertTrue(actual instanceof TaskProgressEvent, "Task event not instance of TaskProgressEvent"); assertEquals(actual.getId(), expected.getId()); assertEquals(((TaskProgressEvent) actual).getProgress(), expected.getProgress()); } private static void assertTaskExecutionEvent(TaskEvent actual, TaskExecutionEvent expected) { assertTrue(actual instanceof TaskExecutionEvent, "Task event not instance of TaskExecutionEvent"); assertEquals(actual.getId(), expected.getId()); assertEquals(((TaskExecutionEvent) actual).getStatus(), expected.getStatus()); } private static void assertTaskResult(TaskResult actual, TaskResultStatus expectedStatus) { assertNotNull(actual); assertNotNull(actual.getId()); assertNotNull(actual.getDescriptorId()); assertEquals(actual.getId(), actual.getDescriptorId()); assertEquals(actual.getOwner(), "owner"); assertEquals(actual.getAuthor(), "author"); assertNotNull(actual.getRegistrationDate()); assertNotNull(actual.getStartDate()); assertNotNull(actual.getEndDate()); assertEquals(actual.getStatus(), expectedStatus); assertNotNull(actual.getParameters()); } public void testFinishedTaskStatus() throws Throwable { final TaskDescriptor descriptor = createMockTaskDescriptor(); final TaskWorker worker = new TaskWorker("owner", "author", descriptor, performer, eventPublisher); executorService.submit(worker).get(); // check events ArgumentCaptor<TaskEvent> eventCaptor = ArgumentCaptor.forClass(TaskEvent.class); Mockito.verify(eventPublisher, new Times(5)).publishEvent(eventCaptor.capture()); List<TaskEvent> events = eventCaptor.getAllValues(); assertTaskProgressEvent(events.get(0), new TaskProgressEvent(worker, descriptor.getId(), null, new TaskProgress(TaskProgress.PENDING_STEP))); assertTaskExecutionEvent(events.get(1), new TaskExecutionEvent(worker, descriptor.getId(), null, TaskExecutionStatus.RUNNING)); assertTaskProgressEvent(events.get(2), new TaskProgressEvent(worker, descriptor.getId(), null, new TaskProgress(TaskProgress.EXECUTING_STEP))); assertTaskProgressEvent(events.get(3), new TaskProgressEvent(worker, descriptor.getId(), null, null)); assertTaskExecutionEvent(events.get(4), new TaskExecutionEvent(worker, descriptor.getId(), null, TaskExecutionStatus.READY)); // check result assertTaskResult(worker.get(), TaskResultStatus.FINISHED); } public void testErrorTaskStatus() throws Throwable { final TaskDescriptor descriptor = createMockTaskDescriptor(); final TaskWorker worker = new TaskWorker("owner", "author", descriptor, performer, eventPublisher); Mockito.doThrow( new UnsupportedOperationException("test error") ).when(performer).performTask(Mockito.any(ITaskProgress.class), Mockito.anyMapOf(String.class, Object.class)); executorService.submit(worker).get(); // check events ArgumentCaptor<TaskExecutionEvent> eventCaptor = ArgumentCaptor.forClass(TaskExecutionEvent.class); Mockito.verify(eventPublisher, new Times(5)).publishEvent(eventCaptor.capture()); List<TaskExecutionEvent> events = eventCaptor.getAllValues(); assertTaskProgressEvent(events.get(0), new TaskProgressEvent(worker, descriptor.getId(), null, new TaskProgress(TaskProgress.PENDING_STEP))); assertTaskExecutionEvent(events.get(1), new TaskExecutionEvent(worker, descriptor.getId(), null, TaskExecutionStatus.RUNNING)); assertTaskProgressEvent(events.get(2), new TaskProgressEvent(worker, descriptor.getId(), null, new TaskProgress(TaskProgress.EXECUTING_STEP))); assertTaskProgressEvent(events.get(3), new TaskProgressEvent(worker, descriptor.getId(), null, null)); assertTaskExecutionEvent(events.get(4), new TaskExecutionEvent(worker, descriptor.getId(), null, TaskExecutionStatus.READY)); // check result TaskResult result = worker.get(); assertTaskResult(result, TaskResultStatus.ERROR); assertEquals(result.getErrorMessage(), "test error"); } public void testCancelTaskStatus() throws Throwable { final TaskDescriptor descriptor = createMockTaskDescriptor(); final TaskWorker worker = new TaskWorker("owner", "author", descriptor, performer, eventPublisher); Mockito.doAnswer( new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { worker.cancel(true); return Collections.<String, Object>emptyMap(); } } ).when(performer).performTask(Mockito.any(ITaskProgress.class), Mockito.anyMapOf(String.class, Object.class)); executorService.submit(worker).get(); // check events ArgumentCaptor<TaskExecutionEvent> eventCaptor = ArgumentCaptor.forClass(TaskExecutionEvent.class); Mockito.verify(eventPublisher, new Times(6)).publishEvent(eventCaptor.capture()); List<TaskExecutionEvent> events = eventCaptor.getAllValues(); assertTaskProgressEvent(events.get(0), new TaskProgressEvent(worker, descriptor.getId(), null, new TaskProgress(TaskProgress.PENDING_STEP))); assertTaskExecutionEvent(events.get(1), new TaskExecutionEvent(worker, descriptor.getId(), null, TaskExecutionStatus.RUNNING)); assertTaskProgressEvent(events.get(2), new TaskProgressEvent(worker, descriptor.getId(), null, new TaskProgress(TaskProgress.EXECUTING_STEP))); assertTaskExecutionEvent(events.get(3), new TaskExecutionEvent(worker, descriptor.getId(), null, TaskExecutionStatus.INTERRUPTING)); assertTaskProgressEvent(events.get(4), new TaskProgressEvent(worker, descriptor.getId(), null, null)); assertTaskExecutionEvent(events.get(5), new TaskExecutionEvent(worker, descriptor.getId(), null, TaskExecutionStatus.READY)); // check result assertTaskResult(worker.get(), TaskResultStatus.CANCELED); } }