title: How to mock an ItemReader in a Spring Batch application using Spock and Groovy
body: <p>I'm trying to write the <strong>tests</strong> for a <strong>Spring Batch</strong> application, specifically on the interaction from the following <strong>reader</strong> when it gets records from a database implementing a simple RowMapper :</p>
  
  <pre class="lang-java prettyprint-override"><code>@Component
  @StepScope
  public class RecordItemReader extends JdbcCursorItemReader&lt;FooDto&gt; {
    @Autowired
    public RecordItemReader(DataSource dataSource) {
      this.setDataSource(dataSource);
      this.setSql(AN_SQL_QUERY);
      this.setRowMapper(new RecordItemMapper());
    }
  }
  </code></pre>
  
  <p>Here is the step definition from the Batch configuration :</p>
  
  <pre class="lang-java prettyprint-override"><code>  @Bean
    public Step step(RecordItemReader recordItemReader,
                     BatchSkipListener skipListener,
                     RecordItemWriter writer,
                     RecordItemProcessor processor,
                     PlatformTransactionManager transactionManager) {
      return stepBuilderFactory
        .get("step1")
        .transactionManager(transactionManager)
        .reader(recordItemReader)
        .faultTolerant()
        .skip(ParseException.class)
        .skip(UnexpectedInputException.class)
        .skipPolicy(new AlwaysSkipItemSkipPolicy())
        .listener(skipListener)
        .processor(processor)
        .writer(writer)
        .build();
    }
  </code></pre>
  
  <p>Everything works fine, except when I try to test using the following :</p>
  
  <pre class="lang-java prettyprint-override"><code>@SpringBatchTest
  @EnableAutoConfiguration
  class BatchSOTest extends Specification {
  
    @Resource
    JobLauncherTestUtils jobLauncherTestUtils
  
    @Resource
    JobRepositoryTestUtils jobRepositoryTestUtils
  
    @Resource
    RecordItemReader recordItemReader
  
    def cleanup() {
      jobRepositoryTestUtils.removeJobExecutions()
    }
  
    def "batch init perfectly"() {
      given:
      // this does not work :
      (1.._) * recordItemReader.read() &gt;&gt; null
  
      when:
      def jobExecution = jobLauncherTestUtils.launchJob()
      def jobInstance = jobExecution.getJobInstance()
      def exitStatus = jobExecution.getExitStatus()
  
      then:
      jobInstance.getJobName() == "soJob"
      exitStatus.getExitCode() == ExitStatus.SUCCESS.getExitCode()
    }
  }
  </code></pre>
  
  <p>I'm not able to Mock the reader properly, I tried various ways like updating reader's properties such as <code>MaxRows</code>, but nothing seems to work.</p>
  
  <p><strong>What is the proper way to update the result of the Reader</strong>?</p>
  
  <p>Or does it needs to be done another way to properly <strong>manipulate the records</strong> from the database <strong>during unit tests</strong>?</p>
  
  <hr>
  
  <hr>
  
  <p><strong>UPDATE:</strong> Ok so I tried a more structured way using a service inside the reader :</p>
  
  <pre class="lang-java prettyprint-override"><code>@Component
  public class FooDtoItemReader extends AbstractItemStreamItemReader&lt;FooDto&gt; {
  
    private List&lt;FooDto&gt; foos ;
  
    private final FooService fooService;
  
    @Autowired
    public FooDtoItemReader(FooService fooService) {
      this.fooService = fooService;
    }
  
    @Override
    public void open(ExecutionContext executionContext) {
      try {
        foos = fooService.getFoos();
  ...
  </code></pre>
  
  <pre class="lang-java prettyprint-override"><code>public interface FooService {
    List&lt;FooDto&gt; getFoos();
  }
  </code></pre>
  
  <pre class="lang-java prettyprint-override"><code>@Service
  public class FooServiceImpl implements FooService {
  
    @Autowired
    private FooDao fooDao;
  
    @Override
    public List&lt;FooDto&gt; getFoos() {
      return fooDao.getFoos();
    }
  }
  </code></pre>
  
  <pre class="lang-java prettyprint-override"><code>@Repository
  public class FooDaoImpl extends JdbcDaoSupport implements FooDao {
  
    @Autowired
    DataSource dataSource;
  
    @PostConstruct
    private void initialize() {
      setDataSource(dataSource);
    }
  
    @Override
    public List&lt;FooDto&gt; getFoos() {
      return getJdbcTemplate().query(SELECT_SQL, new FooMapper());
    }
  
  }
  </code></pre>
  
  <p>Here, I'm facing the problem where I cannot mock properly my Service :</p>
  
  <p>I must be missing something with the test utils.</p>
  
  <pre class="lang-java prettyprint-override"><code>class BatchSOTest extends Specification {
  
    @Resource
    JobLauncherTestUtils jobLauncherTestUtils
  
    @Resource
    JobRepositoryTestUtils jobRepositoryTestUtils
  
    FooService       fooService       = Mock(FooService);
    FooDtoItemReader fooDtoItemReader = new FooDtoItemReader(fooService)
  
    def cleanup() {
      jobRepositoryTestUtils.removeJobExecutions()
    }
  
    def "batch init perfectly (second version)"() {
      given:
      fooDtoItemReader.open(Mock(ExecutionContext))
  
      and:
      // still not working from there :
      (1.._) * fooService.getFoos() &gt;&gt; [createFooEntity(123, "Test")]
  
  
      when:
      def jobExecution = jobLauncherTestUtils.launchJob()
      def jobInstance = jobExecution.getJobInstance()
      def exitStatus = jobExecution.getExitStatus()
  
      then:
      jobInstance.getJobName() == "soJob"
      exitStatus.getExitCode() == ExitStatus.SUCCESS.getExitCode()
    }
  </code></pre>
  
  <p>But if I try to mock from there, it works :</p>
  
  <pre class="lang-java prettyprint-override"><code>class FooDtoItemReaderTest extends Specification {
  
    FooService fooService = Mock(FooService);
    FooDtoItemReader fooDtoItemReader = new FooDtoItemReader(fooService, 0)
  
    def "open gets the foos and reader is initialized"() {
      given: "Foos examples"
      def foos = [
        createFooEntity(123, "A"),
        createFooEntity(456, "B")
      ]
  
      when: "reader is initialized"
      fooDtoItemReader.open(Mock(ExecutionContext))
  
      then: "service get the expected foos"
      1 * fooService.getFoos() &gt;&gt; foos
    }
  </code></pre>
  
  <p>So what am I doing wrong ?</p>