I am new to Spring Batch and I started developping a simple batch application. Now I am thinking of some unit testing unsing JUnit that could be healthy for my app and code ;)
The problem is that I couldn't find any ressource (examples, tutos ...) on the internet that shows how to perform unit testing with Spring Batch when using no XML.
Here is my code to be more clear :
Config class:
package my.company.project.name.batch.config
@Configuration
@EnableBatchProcessing
@ComponentScan({
"my.company.project.name.batch.reader",
"my.company.project.name.batch.tasklet",
"my.company.project.name.batch.processor",
"my.company.project.name.batch.writer"
})
@Import({CommonConfig.class})
public class MyItemBatchConfig {
@Autowired
private StepBuilderFactory steps;
@Autowired
private JobBuilderFactory jobBuilderFactory;
@Autowired
private MyItemTasklet myItemTasklet;
@Bean
public Job myItemJob(@Qualifier("myItem") Step loadProducts){
return jobBuilderFactory.get("myItemJob").start(myMethod).build();
}
@Bean(name= "myItem")
public Step myMethod(){
return steps.get("myItem").tasklet(myItemTasklet).build();
}
}
MyItemReader class :
package my.company.project.name.batch.reader
@Component
public class MyItemReader implements ItemReader<MyItem>{
@Value("${batch.load.produit.csv.file.path}")
private String csvFilePath;
private LinkedList<CsvRawLine> myItems;
@PostConstruct
public void init() {
myItems = new LinkedList<>(CsvUtil.getCsvReader(MyItem.class, csvFilePath));
}
@Override
public MyItem read() throws Exception{
return myItems.poll();
}
}
ItemProcessor class :
package my.company.project.name.batch.processor
@Component
public class MyItemProcessor implements ItemProcessor<MyItem, MyItemProcessorResult> {
public MyItemProcessorResult process(MyItemitem) throws Exception {
//processing business logic
}
}
ItemWriter class :
package my.company.project.name.batch.writer
@Component
public class MyItemWriter implements ItemWriter<MyItem> {
@Override
public void write(List<? extends MyItem> myItems) throws Exception {
//writer business logic
}
}
MyItemTasklet class that will call all the previous classes in order to achieve the task wanted by the batch:
package package my.company.project.name.batch.tasklet
@Component
public class MyItemBatchTasklet implements Tasklet{
@Autowired
public MyItemReader myItemReader;
@Autowired
public MyItemProcessor myItemProcessor;
@Autowired
public MyItemeWriter myItemWriter;
@Override
public RepeatStatus execute execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
//calling myItemReader, myItemProcessor and myItemWriter to do the business logic
return RepeatStatus.FINISHED
}
}
MyItemTasklet class that will launch the tasklet by its main method :
package package my.company.project.name.batch
public class MyItemTaskletLauncher{
public MyItemTaskletLauncher(){
//No implementation
}
public static void main (String[] args) throws IOException, JobExecutionException, NamingException {
Launcher.launchWithConfig("Launching MyItemTasklet ...", MyItemBatchConfig.class,false);
}
}
I made a simple batch application using Spring Batch and MyBatis and JUnit.
The test codes of application runs unit testing without XML.
Here is test class for Job.
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {xxx.class, yyy.class, zzz.class, xxxJobLauncherTestUtils.class})
public class JobTest {
@Autowired
@Qualifier(value = "xxxJobLauncherTestUtils")
private JobLauncherTestUtils xxxJobLauncherTestUtils;
@Test
public void testXxxJob() throws Exception {
JobExecution jobExecution = xxxJobLauncherTestUtils.launchJob();
assertThat(jobExecution.getStatus(), is(BatchStatus.COMPLETED));
}
}
@Component(value = "xxxJobLauncherTestUtils")
class XxxjobLauncherTestUtils extends JobLauncherTestUtils {
@Autowired
@Qualifier(value = "xxxJob")
@Override
public void setJob(Job job) {
super.setJob(job);
}
}
About details, please see the below link.
https://github.com/Maeno/spring-batch-example/tree/master/src/test
I hope that it will be helpful.