Main Tutorials

Spring Batch unit test example

In this tutorial, we will show you how to unit test Spring batch jobs with jUnit and TestNG frameworks. To unit test batch job, declares spring-batch-test.jar, @autowired the JobLauncherTestUtils, launch the job or step, and assert the execution status.

1. Unit Test Dependencies

To unit test Spring batch, declares following dependencies :

pom.xml

	<!-- Spring Batch dependencies -->
	<dependency>
		<groupId>org.springframework.batch</groupId>
		<artifactId>spring-batch-core</artifactId>
		<version>2.2.0.RELEASE</version>
	</dependency>
	<dependency>
		<groupId>org.springframework.batch</groupId>
		<artifactId>spring-batch-infrastructure</artifactId>
		<version>2.2.0.RELEASE</version>
	</dependency>
	
	<!-- Spring Batch unit test -->	
	<dependency>
		<groupId>org.springframework.batch</groupId>
		<artifactId>spring-batch-test</artifactId>
		<version>2.2.0.RELEASE</version>
	</dependency>
		
	<!-- Junit -->
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.11</version>
		<scope>test</scope>
	</dependency>

	<!-- Testng -->
	<dependency>
		<groupId>org.testng</groupId>
		<artifactId>testng</artifactId>
		<version>6.8.5</version>
		<scope>test</scope>
	</dependency>	

2. Spring Batch Jobs

A simple job, later unit test the execution status.

spring-batch-job.xml

    <!-- ...... -->
    <batch:job id="testJob">
	<batch:step id="step1">
	    <batch:tasklet>
		<batch:chunk reader="xmlItemReader" 
			writer="oracleItemWriter"
			commit-interval="1">
		</batch:chunk>
	    </batch:tasklet>
	</batch:step>
    </batch:job>

3. jUnit Examples

Launches a the job and assert the execution status.

AppTest.java

package com.mkyong;

import static org.junit.Assert.assertEquals;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
    "classpath:spring/batch/jobs/spring-batch-job.xml",
    "classpath:spring/batch/config/context.xml",
    "classpath:spring/batch/config/test-context.xml"})
public class AppTest {

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;
    
    @Test
    public void launchJob() throws Exception {

	//testing a job
        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        
	//Testing a individual step
        //JobExecution jobExecution = jobLauncherTestUtils.launchStep("step1");
        
        assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus());
        
    }
}

P.S Assume context.xml is declared all the require Spring batch core components, like jobRepository and etc.

This JobLauncherTestUtils must be declares manually.

test-context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
	http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
 
    <!-- Spring should auto load this bean -->
    <bean class="org.springframework.batch.test.JobLauncherTestUtils"/>
    
</beans>

4. TestNG Examples

Equivalent example in TestNG framework.

AppTest2.java

package com.mkyong;

import org.springframework.batch.core.BatchStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.Test;

@ContextConfiguration(locations = {
    "classpath:spring/batch/jobs/spring-batch-job.xml",
    "classpath:spring/batch/config/context.xml",
    "classpath:spring/batch/config/test-context.xml"})
public class AppTest2 extends AbstractTestNGSpringContextTests {

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    
    @Test
    public void launchJob() throws Exception {

        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        Assert.assertEquals(jobExecution.getStatus(), BatchStatus.COMPLETED);
        
    }
}

Done.

Download Source Code

Download it – SpringBatch-UnitTest-Example.zip (83 KB)

References

  1. JobLauncherTestUtils JavaDoc
  2. Spring Batch Unit Testing official documentation

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
7 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Shreyas K
8 years ago

Hi,

Thanks a lot for this wonderful post.
I have implemented your example and it’s working fine, except for the last Assert statement.

The issue is that, call to launchJob() is asynchronous and soon after the call to launchJob(), next line gets executed i.e. (Assert.assertEquals(jobExecution.getStatus(), BatchStatus.COMPLETED);)
and the status of my job is STARTED so the assert fails.

For running the test case, I have added the while condition checking for COMPLETED status, so that the test case would succeed.

JobExecution jobExecution = jobLauncherTestUtils.launchJob();
while(jobExecution.getStatus() != BatchStatus.COMPLETED)
{
continue;
}
Assert.assertEquals(jobExecution.getStatus(), BatchStatus.COMPLETED);

Just wondering, is there any better way of doing instead of while loop.

Julien
5 years ago
Reply to  Shreyas K

Hi,

I had the same problem. This is because my taskExecutor was Asynchrone.
So I defined for my test only, a new jobLauncher with a SyncTask Excecutor :

and a new JobLauncher
@Component
public class Test1JobLauncher {

@Inject
@Qualifier(value = “aggregate-test1-datamart”)
private Job job;

@Inject
@Qualifier(value = “jobLauncherSynchrone”)
private JobLauncher jobLauncher;

@Inject
private JobRepository jobRepository;

private JobLauncherTestUtils jobLauncherTestUtils;

private void initializeJobLauncherTestUtils() {
this.jobLauncherTestUtils = new JobLauncherTestUtils();
this.jobLauncherTestUtils.setJobLauncher(jobLauncher);
this.jobLauncherTestUtils.setJobRepository(jobRepository);
this.jobLauncherTestUtils.setJob(job);
}

@Before
public void setUp() throws Exception {
this.initializeJobLauncherTestUtils();
}

public JobLauncherTestUtils getJobLauncherTestUtils() {
return jobLauncherTestUtils;
}
}

Prashant
1 year ago

Hi, do you have latest tutorial on Spring Batch unit testing ?
Can you please share ?

Gautam
1 year ago

Hi,

Is it possible to test JobLauncher.run using mockito. I tried mocking it, but no matter what I do it always returns null. Here are my code pieces

Mocking

@MockBean
JobLauncher jobLauncher
In Test Method

doReturn(jobExecution).when(jobLauncher.run(any(Job.class),any(JobParameters.class)));

So with this whenever run is invoked its returning null. Can you guide me on this?

Saocro
5 years ago

Hi, how about if there is a multiple job? Can you help me how to run the another job? I tried it will your example but I ended up running only one job. Thanks

Jérôme V
9 years ago

Hi,

Thx for this 🙂

kim hyungsuk
9 years ago

thank.~ i want it~