Unit Testing using JUnit for Spring Batch without XML configuration

Ghassen picture Ghassen · Jul 28, 2017 · Viewed 7k times · Source

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);
    }
}

Answer

user8528058 picture user8528058 · Aug 28, 2017

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.