BATCH-1344: added JobRunnerTestUtils and deprecated the old AbstractJobTests
This commit is contained in:
@@ -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 {
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* 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.
|
||||
* </p>
|
||||
*
|
||||
* @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<String, JobParameter> parameters = new HashMap<String, JobParameter>();
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
}
|
||||
|
||||
10
spring-batch-test/src/test/resources/job-runner-context.xml
Normal file
10
spring-batch-test/src/test/resources/job-runner-context.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
|
||||
|
||||
<context:annotation-config/>
|
||||
<bean class="org.springframework.batch.test.JobRunnerTestUtils"/>
|
||||
|
||||
</beans>
|
||||
Reference in New Issue
Block a user