diff --git a/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java b/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java new file mode 100644 index 000000000..0b6ed6c96 --- /dev/null +++ b/spring-batch-core/src/test/java/org/springframework/batch/core/step/AbstractStepTests.java @@ -0,0 +1,163 @@ +package org.springframework.batch.core.step; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.springframework.batch.core.JobExecution; +import org.springframework.batch.core.JobInstance; +import org.springframework.batch.core.JobParameters; +import org.springframework.batch.core.StepExecution; +import org.springframework.batch.core.StepExecutionListener; +import org.springframework.batch.core.job.JobSupport; +import org.springframework.batch.item.ExecutionContext; +import org.springframework.batch.repeat.ExitStatus; + +/** + * Tests for {@link AbstractStep}. + */ +public class AbstractStepTests extends TestCase { + + AbstractStep tested = new EventTrackingStep(); + + StepExecutionListener listener1 = new EventTrackingListener("listener1"); + + StepExecutionListener listener2 = new EventTrackingListener("listener2"); + + /** + * Sequence of events encountered during step execution. + */ + final List events = new ArrayList(); + + final StepExecution execution = new StepExecution(tested, new JobExecution(new JobInstance(new Long(1), + new JobParameters(), new JobSupport()))); + + /** + * Fills the events list when abstract methods are called. + */ + private class EventTrackingStep extends AbstractStep { + + protected void open(ExecutionContext ctx) throws Exception { + events.add("open"); + } + + protected ExitStatus doExecute(StepExecution stepExecution) throws Exception { + assertSame(execution, stepExecution); + events.add("doExecute"); + return ExitStatus.FINISHED; + } + + protected void close(ExecutionContext ctx) throws Exception { + events.add("close"); + } + } + + /** + * Fills the events list when listener methods are called, prefixed with the + * name of the listener. + */ + private class EventTrackingListener implements StepExecutionListener { + + private String name; + + public EventTrackingListener(String name) { + this.name = name; + } + + private String getEvent(String event) { + return name + "#" + event; + } + + public ExitStatus afterStep(StepExecution stepExecution) { + assertSame(execution, stepExecution); + events.add(getEvent("afterStep")); + return stepExecution.getExitStatus(); + } + + public ExitStatus onErrorInStep(StepExecution stepExecution, Throwable e) { + assertSame(execution, stepExecution); + events.add(getEvent("onErrorInStep")); + return stepExecution.getExitStatus(); + } + + public void beforeStep(StepExecution stepExecution) { + assertSame(execution, stepExecution); + events.add(getEvent("beforeStep")); + } + + } + + protected void setUp() throws Exception { + tested.setJobRepository(new JobRepositorySupport()); + } + + /** + * Typical step execution scenario. + */ + public void testExecute() throws Exception { + tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); + tested.execute(execution); + + int i = 0; + assertEquals("listener1#beforeStep", events.get(i++)); + assertEquals("listener2#beforeStep", events.get(i++)); + assertEquals("open", events.get(i++)); + assertEquals("doExecute", events.get(i++)); + assertEquals("listener1#afterStep", events.get(i++)); + assertEquals("listener2#afterStep", events.get(i++)); + assertEquals("close", events.get(i++)); + assertEquals(7, events.size()); + + assertEquals(ExitStatus.FINISHED, execution.getExitStatus()); + } + + /** + * Exception during business processing. + */ + public void testFailure() throws Exception { + tested = new EventTrackingStep() { + protected ExitStatus doExecute(StepExecution stepExecution) throws Exception { + super.doExecute(stepExecution); + throw new RuntimeException("crash!"); + } + }; + tested.setJobRepository(new JobRepositorySupport()); + tested.setStepExecutionListeners(new StepExecutionListener[] { listener1, listener2 }); + + try { + tested.execute(execution); + fail(); + } + catch (RuntimeException expected) { + assertEquals("crash!", expected.getMessage()); + } + + int i = 0; + assertEquals("listener1#beforeStep", events.get(i++)); + assertEquals("listener2#beforeStep", events.get(i++)); + assertEquals("open", events.get(i++)); + assertEquals("doExecute", events.get(i++)); + assertEquals("listener1#onErrorInStep", events.get(i++)); + assertEquals("listener2#onErrorInStep", events.get(i++)); + assertEquals("close", events.get(i++)); + assertEquals(7, events.size()); + + assertEquals(ExitStatus.FAILED.getExitCode(), execution.getExitStatus().getExitCode()); + } + + /** + * JobRepository is a required property. + */ + public void testAfterPropertiesSet() throws Exception { + tested.setJobRepository(null); + try { + tested.afterPropertiesSet(); + fail(); + } + catch (IllegalArgumentException e) { + // expected + } + } + +}