package org.springframework.batch.integration.partition;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.concurrent.TimeoutException;
import org.junit.Test;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.explore.JobExplorer;
import org.springframework.batch.core.partition.StepExecutionSplitter;
import org.springframework.integration.MessageTimeoutException;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.messaging.Message;
import org.springframework.messaging.PollableChannel;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
/**
*
* @author Will Schipp
* @author Michael Minella
*
*/
@SuppressWarnings("raw")
public class MessageChannelPartitionHandlerTests {
private MessageChannelPartitionHandler messageChannelPartitionHandler;
@Test
public void testNoPartitions() throws Exception {
//execute with no default set
messageChannelPartitionHandler = new MessageChannelPartitionHandler();
//mock
StepExecution masterStepExecution = mock(StepExecution.class);
StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class);
//execute
Collection<StepExecution> executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, masterStepExecution);
//verify
assertNull(executions);
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Test
public void testHandleNoReply() throws Exception {
//execute with no default set
messageChannelPartitionHandler = new MessageChannelPartitionHandler();
//mock
StepExecution masterStepExecution = mock(StepExecution.class);
StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class);
MessagingTemplate operations = mock(MessagingTemplate.class);
Message message = mock(Message.class);
//when
HashSet<StepExecution> stepExecutions = new HashSet<>();
stepExecutions.add(new StepExecution("step1", new JobExecution(5L)));
when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions);
when(message.getPayload()).thenReturn(Collections.emptyList());
when(operations.receive((PollableChannel) any())).thenReturn(message);
//set
messageChannelPartitionHandler.setMessagingOperations(operations);
//execute
Collection<StepExecution> executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, masterStepExecution);
//verify
assertNotNull(executions);
assertTrue(executions.isEmpty());
}
@SuppressWarnings({"unchecked", "rawtypes"})
@Test
public void testHandleWithReplyChannel() throws Exception {
//execute with no default set
messageChannelPartitionHandler = new MessageChannelPartitionHandler();
//mock
StepExecution masterStepExecution = mock(StepExecution.class);
StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class);
MessagingTemplate operations = mock(MessagingTemplate.class);
Message message = mock(Message.class);
PollableChannel replyChannel = mock(PollableChannel.class);
//when
HashSet<StepExecution> stepExecutions = new HashSet<>();
stepExecutions.add(new StepExecution("step1", new JobExecution(5L)));
when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions);
when(message.getPayload()).thenReturn(Collections.emptyList());
when(operations.receive(replyChannel)).thenReturn(message);
//set
messageChannelPartitionHandler.setMessagingOperations(operations);
messageChannelPartitionHandler.setReplyChannel(replyChannel);
//execute
Collection<StepExecution> executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, masterStepExecution);
//verify
assertNotNull(executions);
assertTrue(executions.isEmpty());
}
@SuppressWarnings("rawtypes")
@Test(expected = MessageTimeoutException.class)
public void messageReceiveTimeout() throws Exception {
//execute with no default set
messageChannelPartitionHandler = new MessageChannelPartitionHandler();
//mock
StepExecution masterStepExecution = mock(StepExecution.class);
StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class);
MessagingTemplate operations = mock(MessagingTemplate.class);
Message message = mock(Message.class);
//when
HashSet<StepExecution> stepExecutions = new HashSet<>();
stepExecutions.add(new StepExecution("step1", new JobExecution(5L)));
when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions);
when(message.getPayload()).thenReturn(Collections.emptyList());
//set
messageChannelPartitionHandler.setMessagingOperations(operations);
//execute
messageChannelPartitionHandler.handle(stepExecutionSplitter, masterStepExecution);
}
@Test
public void testHandleWithJobRepositoryPolling() throws Exception {
//execute with no default set
messageChannelPartitionHandler = new MessageChannelPartitionHandler();
//mock
JobExecution jobExecution = new JobExecution(5L, new JobParameters());
StepExecution masterStepExecution = new StepExecution("step1", jobExecution, 1L);
StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class);
MessagingTemplate operations = mock(MessagingTemplate.class);
JobExplorer jobExplorer = mock(JobExplorer.class);
//when
HashSet<StepExecution> stepExecutions = new HashSet<>();
StepExecution partition1 = new StepExecution("step1:partition1", jobExecution, 2L);
StepExecution partition2 = new StepExecution("step1:partition2", jobExecution, 3L);
StepExecution partition3 = new StepExecution("step1:partition3", jobExecution, 4L);
StepExecution partition4 = new StepExecution("step1:partition3", jobExecution, 4L);
partition1.setStatus(BatchStatus.COMPLETED);
partition2.setStatus(BatchStatus.COMPLETED);
partition3.setStatus(BatchStatus.STARTED);
partition4.setStatus(BatchStatus.COMPLETED);
stepExecutions.add(partition1);
stepExecutions.add(partition2);
stepExecutions.add(partition3);
when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions);
when(jobExplorer.getStepExecution(eq(5L), any(Long.class))).thenReturn(partition2, partition1, partition3, partition3, partition3, partition3, partition4);
//set
messageChannelPartitionHandler.setMessagingOperations(operations);
messageChannelPartitionHandler.setJobExplorer(jobExplorer);
messageChannelPartitionHandler.setStepName("step1");
messageChannelPartitionHandler.setPollInterval(500L);
messageChannelPartitionHandler.afterPropertiesSet();
//execute
Collection<StepExecution> executions = messageChannelPartitionHandler.handle(stepExecutionSplitter, masterStepExecution);
//verify
assertNotNull(executions);
assertEquals(3, executions.size());
assertTrue(executions.contains(partition1));
assertTrue(executions.contains(partition2));
assertTrue(executions.contains(partition4));
//verify
verify(operations, times(3)).send(any(Message.class));
}
@Test(expected = TimeoutException.class)
public void testHandleWithJobRepositoryPollingTimeout() throws Exception {
//execute with no default set
messageChannelPartitionHandler = new MessageChannelPartitionHandler();
//mock
JobExecution jobExecution = new JobExecution(5L, new JobParameters());
StepExecution masterStepExecution = new StepExecution("step1", jobExecution, 1L);
StepExecutionSplitter stepExecutionSplitter = mock(StepExecutionSplitter.class);
MessagingTemplate operations = mock(MessagingTemplate.class);
JobExplorer jobExplorer = mock(JobExplorer.class);
//when
HashSet<StepExecution> stepExecutions = new HashSet<>();
StepExecution partition1 = new StepExecution("step1:partition1", jobExecution, 2L);
StepExecution partition2 = new StepExecution("step1:partition2", jobExecution, 3L);
StepExecution partition3 = new StepExecution("step1:partition3", jobExecution, 4L);
partition1.setStatus(BatchStatus.COMPLETED);
partition2.setStatus(BatchStatus.COMPLETED);
partition3.setStatus(BatchStatus.STARTED);
stepExecutions.add(partition1);
stepExecutions.add(partition2);
stepExecutions.add(partition3);
when(stepExecutionSplitter.split(any(StepExecution.class), eq(1))).thenReturn(stepExecutions);
when(jobExplorer.getStepExecution(eq(5L), any(Long.class))).thenReturn(partition2, partition1, partition3);
//set
messageChannelPartitionHandler.setMessagingOperations(operations);
messageChannelPartitionHandler.setJobExplorer(jobExplorer);
messageChannelPartitionHandler.setStepName("step1");
messageChannelPartitionHandler.setTimeout(1000L);
messageChannelPartitionHandler.afterPropertiesSet();
//execute
messageChannelPartitionHandler.handle(stepExecutionSplitter, masterStepExecution);
}
}