+
+
-
+
+
+
+
+
diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/MultilineJobFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/MultilineJobFunctionalTests-context.xml
deleted file mode 100644
index 638ccc88e..000000000
--- a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/MultilineJobFunctionalTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/MultilineOrderJobFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/MultilineOrderJobFunctionalTests-context.xml
deleted file mode 100644
index 8c516d2c7..000000000
--- a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/MultilineOrderJobFunctionalTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/ParallelJobFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/ParallelJobFunctionalTests-context.xml
deleted file mode 100644
index 44f3288b3..000000000
--- a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/ParallelJobFunctionalTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/PartitionFileJobFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/PartitionFileJobFunctionalTests-context.xml
deleted file mode 100644
index 78a964a52..000000000
--- a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/PartitionFileJobFunctionalTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/PartitionJdbcJobFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/PartitionJdbcJobFunctionalTests-context.xml
deleted file mode 100644
index d53fbabc6..000000000
--- a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/PartitionJdbcJobFunctionalTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/RestartFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/RestartFunctionalTests-context.xml
deleted file mode 100644
index 76460ba57..000000000
--- a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/RestartFunctionalTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/RetrySampleFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/RetrySampleFunctionalTests-context.xml
deleted file mode 100644
index 5ae2aca9a..000000000
--- a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/RetrySampleFunctionalTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/TaskletJobFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/TaskletJobFunctionalTests-context.xml
deleted file mode 100644
index eca4abea3..000000000
--- a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/TaskletJobFunctionalTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/TradeJobFunctionalTests-context.xml b/spring-batch-samples/src/test/resources/org/springframework/batch/sample/TradeJobFunctionalTests-context.xml
deleted file mode 100644
index c3b224ce7..000000000
--- a/spring-batch-samples/src/test/resources/org/springframework/batch/sample/TradeJobFunctionalTests-context.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
-
-
-
diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/AbstractJobTests.java b/spring-batch-test/src/main/java/org/springframework/batch/test/AbstractJobTests.java
index f740baf81..ed6e0f800 100644
--- a/spring-batch-test/src/main/java/org/springframework/batch/test/AbstractJobTests.java
+++ b/spring-batch-test/src/main/java/org/springframework/batch/test/AbstractJobTests.java
@@ -64,6 +64,8 @@ import org.springframework.context.ApplicationContextAware;
* @author Lucas Ward
* @author Dan Garrette
* @since 2.0
+ *
+ * @deprecated (from 2.1) use {@link JobRunnerTestUtils} instead
*/
public abstract class AbstractJobTests implements ApplicationContextAware {
diff --git a/spring-batch-test/src/main/java/org/springframework/batch/test/JobRunnerTestUtils.java b/spring-batch-test/src/main/java/org/springframework/batch/test/JobRunnerTestUtils.java
new file mode 100644
index 000000000..1635781ce
--- /dev/null
+++ b/spring-batch-test/src/main/java/org/springframework/batch/test/JobRunnerTestUtils.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2006-2007 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.batch.test;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.batch.core.Job;
+import org.springframework.batch.core.JobExecution;
+import org.springframework.batch.core.JobParameter;
+import org.springframework.batch.core.JobParameters;
+import org.springframework.batch.core.Step;
+import org.springframework.batch.core.job.AbstractJob;
+import org.springframework.batch.core.job.SimpleJob;
+import org.springframework.batch.core.job.flow.FlowJob;
+import org.springframework.batch.core.launch.JobLauncher;
+import org.springframework.batch.core.repository.JobRepository;
+import org.springframework.batch.item.ExecutionContext;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+
+/**
+ *
+ * Utility class for testing batch jobs. It provides methods for launching an
+ * entire {@link AbstractJob}, allowing for end to end testing of individual
+ * steps, without having to run every step in the job. Any test classes using
+ * this utility can set up an instance in the {@link ApplicationContext} as part
+ * of the Spring test framework.
+ *
+ *
+ *
+ * This class also provides the ability to run {@link Step}s from a
+ * {@link FlowJob} or {@link SimpleJob} individually. By launching {@link Step}s
+ * within a {@link Job} on their own, end to end testing of individual steps can
+ * be performed without having to run every step in the job.
+ *
+ *
+ *
+ * It should be noted that using any of the methods that don't contain
+ * {@link JobParameters} in their signature, will result in one being created
+ * with the current system time as a parameter. This will ensure restartability
+ * when no parameters are provided.
+ *
+ *
+ * @author Lucas Ward
+ * @author Dan Garrette
+ * @author Dave Syer
+ * @since 2.1
+ */
+public class JobRunnerTestUtils {
+
+ /** Logger */
+ protected final Log logger = LogFactory.getLog(getClass());
+
+ private JobLauncher jobLauncher;
+
+ private AbstractJob job;
+
+ private JobRepository jobRepository;
+
+ private StepRunner stepRunner;
+
+ /**
+ * The Job instance that can be manipulated (e.g. launched) in this utility.
+ *
+ * @param job the {@link AbstractJob} to use
+ */
+ @Autowired
+ public void setJob(AbstractJob job) {
+ this.job = job;
+ }
+
+ /**
+ * The {@link JobRepository} to use for creating new {@link JobExecution}
+ * instances.
+ *
+ * @param jobRepository a {@link JobRepository}
+ */
+ @Autowired
+ public void setJobRepository(JobRepository jobRepository) {
+ this.jobRepository = jobRepository;
+ }
+
+ /**
+ * @return the job repository
+ */
+ public JobRepository getJobRepository() {
+ return jobRepository;
+ }
+
+ /**
+ * @return the job
+ */
+ public AbstractJob getJob() {
+ return job;
+ }
+
+ /**
+ * A {@link JobLauncher} instance that can be used to launch jobs.
+ *
+ * @param jobLauncher a job launcher
+ */
+ @Autowired
+ public void setJobLauncher(JobLauncher jobLauncher) {
+ this.jobLauncher = jobLauncher;
+ }
+
+ /**
+ * @return the job launcher
+ */
+ public JobLauncher getJobLauncher() {
+ return jobLauncher;
+ }
+
+ /**
+ * Launch the entire job, including all steps.
+ *
+ * @return JobExecution, so that the test can validate the exit status
+ * @throws Exception
+ */
+ public JobExecution launchJob() throws Exception {
+ return this.launchJob(this.getUniqueJobParameters());
+ }
+
+ /**
+ * Launch the entire job, including all steps
+ *
+ * @param jobParameters
+ * @return JobExecution, so that the test can validate the exit status
+ * @throws Exception
+ */
+ public JobExecution launchJob(JobParameters jobParameters) throws Exception {
+ return getJobLauncher().run(this.job, jobParameters);
+ }
+
+ /**
+ * @return a new JobParameters object containing only a parameter for the
+ * current timestamp, to ensure that the job instance will be unique.
+ */
+ public JobParameters getUniqueJobParameters() {
+ Map parameters = new HashMap();
+ parameters.put("timestamp", new JobParameter(new Date().getTime()));
+ return new JobParameters(parameters);
+ }
+
+ /**
+ * Convenient method for subclasses to grab a {@link StepRunner} for running
+ * steps by name.
+ *
+ * @return a {@link StepRunner}
+ */
+ protected StepRunner getStepRunner() {
+ if (this.stepRunner == null) {
+ this.stepRunner = new StepRunner(getJobLauncher(), getJobRepository());
+ }
+ return this.stepRunner;
+ }
+
+ /**
+ * Launch just the specified step in the job. A unique set of JobParameters
+ * will automatically be generated. An IllegalStateException is thrown if
+ * there is no Step with the given name.
+ *
+ * @param stepName The name of the step to launch
+ * @return JobExecution
+ */
+ public JobExecution launchStep(String stepName) {
+ return this.launchStep(stepName, this.getUniqueJobParameters(), null);
+ }
+
+ /**
+ * Launch just the specified step in the job. A unique set of JobParameters
+ * will automatically be generated. An IllegalStateException is thrown if
+ * there is no Step with the given name.
+ *
+ * @param stepName The name of the step to launch
+ * @param jobExecutionContext An ExecutionContext whose values will be
+ * loaded into the Job ExecutionContext prior to launching the step.
+ * @return JobExecution
+ */
+ public JobExecution launchStep(String stepName, ExecutionContext jobExecutionContext) {
+ return this.launchStep(stepName, this.getUniqueJobParameters(), jobExecutionContext);
+ }
+
+ /**
+ * Launch just the specified step in the job. An IllegalStateException is
+ * thrown if there is no Step with the given name.
+ *
+ * @param stepName The name of the step to launch
+ * @param jobParameters The JobParameters to use during the launch
+ * @return JobExecution
+ */
+ public JobExecution launchStep(String stepName, JobParameters jobParameters) {
+ return this.launchStep(stepName, jobParameters, null);
+ }
+
+ /**
+ * Launch just the specified step in the job. An IllegalStateException is
+ * thrown if there is no Step with the given name.
+ *
+ * @param stepName The name of the step to launch
+ * @param jobParameters The JobParameters to use during the launch
+ * @param jobExecutionContext An ExecutionContext whose values will be
+ * loaded into the Job ExecutionContext prior to launching the step.
+ * @return JobExecution
+ */
+ public JobExecution launchStep(String stepName, JobParameters jobParameters, ExecutionContext jobExecutionContext) {
+ Step step = this.job.getStep(stepName);
+ if (step == null) {
+ step = this.job.getStep(this.job.getName() + "." + stepName);
+ }
+ if (step == null) {
+ throw new IllegalStateException("No Step found with name: [" + stepName + "]");
+ }
+ return getStepRunner().launchStep(step, jobParameters, jobExecutionContext);
+ }
+}
diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/AbstractSampleJobTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/AbstractSampleJobTests.java
index 6200adcf5..249b772d8 100644
--- a/spring-batch-test/src/test/java/org/springframework/batch/test/AbstractSampleJobTests.java
+++ b/spring-batch-test/src/test/java/org/springframework/batch/test/AbstractSampleJobTests.java
@@ -12,6 +12,7 @@ import org.springframework.batch.test.sample.SampleTasklet;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
+import org.springframework.test.context.ContextConfiguration;
/**
* This is an abstract test class to be used by test classes to test the
@@ -20,10 +21,14 @@ import org.springframework.jdbc.core.simple.SimpleJdbcTemplate;
* @author Dan Garrette
* @since 2.0
*/
-public abstract class AbstractSampleJobTests extends AbstractJobTests {
+@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/job-runner-context.xml" })
+public abstract class AbstractSampleJobTests {
private SimpleJdbcTemplate jdbcTemplate;
+ @Autowired
+ private JobRunnerTestUtils jobRunnerUtils;
+
@Autowired
@Qualifier("tasklet2")
private SampleTasklet tasklet2;
@@ -46,25 +51,25 @@ public abstract class AbstractSampleJobTests extends AbstractJobTests {
@Test
public void testJob() throws Exception {
- assertEquals(BatchStatus.COMPLETED, this.launchJob().getStatus());
+ assertEquals(BatchStatus.COMPLETED, jobRunnerUtils.launchJob().getStatus());
this.verifyTasklet(1);
this.verifyTasklet(2);
}
@Test(expected = IllegalStateException.class)
public void testNonExistentStep() {
- launchStep("nonExistent");
+ jobRunnerUtils.launchStep("nonExistent");
}
@Test
public void testStep1Execution() {
- assertEquals(BatchStatus.COMPLETED, this.launchStep("step1").getStatus());
+ assertEquals(BatchStatus.COMPLETED, jobRunnerUtils.launchStep("step1").getStatus());
this.verifyTasklet(1);
}
@Test
public void testStep2Execution() {
- assertEquals(BatchStatus.COMPLETED, this.launchStep("step2").getStatus());
+ assertEquals(BatchStatus.COMPLETED, jobRunnerUtils.launchStep("step2").getStatus());
this.verifyTasklet(2);
}
@@ -72,7 +77,7 @@ public abstract class AbstractSampleJobTests extends AbstractJobTests {
public void testStepLaunchJobContextEntry() {
ExecutionContext jobContext = new ExecutionContext();
jobContext.put("key1", "value1");
- assertEquals(BatchStatus.COMPLETED, this.launchStep("step2", jobContext).getStatus());
+ assertEquals(BatchStatus.COMPLETED, jobRunnerUtils.launchStep("step2", jobContext).getStatus());
this.verifyTasklet(2);
assertTrue(tasklet2.jobContextEntryFound);
}
diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleFlowJobTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleFlowJobTests.java
index 4ccaaa5cf..7e0da03d3 100644
--- a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleFlowJobTests.java
+++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleFlowJobTests.java
@@ -7,13 +7,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* This class will specifically test the capabilities of
- * {@link AbstractSampleJobTests} to test {@link FlowJob}s.
+ * {@link JobRepositoryTestUtils} to test {@link FlowJob}s.
*
* @author Dan Garrette
* @since 2.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/sampleFlowJob.xml" })
+@ContextConfiguration(locations = "/jobs/sampleFlowJob.xml")
public class SampleFlowJobTests extends AbstractSampleJobTests {
}
diff --git a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleSimpleJobTests.java b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleSimpleJobTests.java
index 24eedd98a..f8f4e86ee 100644
--- a/spring-batch-test/src/test/java/org/springframework/batch/test/SampleSimpleJobTests.java
+++ b/spring-batch-test/src/test/java/org/springframework/batch/test/SampleSimpleJobTests.java
@@ -7,13 +7,13 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* This class will specifically test the capabilities of
- * {@link AbstractSampleJobTests} to test {@link SimpleJob}s.
+ * {@link JobRepositoryTestUtils} to test {@link SimpleJob}s.
*
* @author Dan Garrette
* @since 2.0
*/
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = { "/simple-job-launcher-context.xml", "/jobs/sampleSimpleJob.xml" })
+@ContextConfiguration(locations = "/jobs/sampleSimpleJob.xml")
public class SampleSimpleJobTests extends AbstractSampleJobTests {
-
+
}
diff --git a/spring-batch-test/src/test/resources/job-runner-context.xml b/spring-batch-test/src/test/resources/job-runner-context.xml
new file mode 100644
index 000000000..e058c2d45
--- /dev/null
+++ b/spring-batch-test/src/test/resources/job-runner-context.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+