Using @MockBean to mock an ItemReader with @BeforeStep Throws Exception to many methods with @Beforestep anotation. How do I solve it?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


Using @MockBean to mock an ItemReader with @BeforeStep Throws Exception to many methods with @Beforestep anotation. How do I solve it?



I have my own Implementation of an ItemReader with two methods.


public class Reader implements ItemReader<Integer> {

private final Logger logger = LoggerFactory.getLogger(getClass());
private Iterator<Integer> iterator;

@Override
public Integer read() throws UnexpectedInputException, ParseException, NonTransientResourceException {
if(iterator.hasNext()){
return iterator.next();
}
return null;
}

@BeforeStep
public void init(StepExecution stepExecution){
List<Integer> integerList = (List<Integer>)stepExecution.getJobExecution().getExecutionContext().get(CKEY_ERROREVENT_IDS);
this.iterator = integerList.iterator();
}
}



When I try to run this within a spring-batch context and mocking the ItemReader with @MockBean the application context throws:


@MockBean



java.lang.IllegalArgumentException: found more than one method on target class [Reader$MockitoMock$368106910] with the annotation type [BeforeStep].



Below is how I start the job.


@MockBean
private Reader reader;

@Test
public void readerTest(){
JobParameters jobParameters = new JobParametersBuilder()
.addString("triggerId", UUID.randomUUID().toString()).toJobParameters();
JobExecution jobExecution = jobLauncher.run(processEventJob, jobParameters);
}





Could it be related to this post? forum.spring.io/forum/spring-projects/batch/…, since mockito creates a subclass of the class-to-mock at runtime?
– Maarten
Apr 25 at 15:13





No I have seen the post and it does not solve the problem.
– PlickPlick
Apr 26 at 15:42





Could you also post the code for the ErrorEventReader class? That seems to be the class you are creating the actual mock of? Does it extend Reader?
– Maarten
Apr 26 at 18:02





This is what it should look like.
– PlickPlick
Apr 27 at 6:12




2 Answers
2



I've been able to reproduce your issue. After that, I've replaced the mock with a child class of your Reader.


@Component
public class ChildReader extends Reader{

public void init(StepExecution stepExecution){
super.init(stepExecution);
}
}



This gives the same exception.
At runtime, Mockito also creates as subclass of your Reader. I think that this is causing your problem.



In this post, the same issue as described:
http://forum.spring.io/forum/spring-projects/batch/98067-beforestep-in-abstract-class
I cannot find any reference to it being fixed.



What you can do to resolve this issue is extract the code you wish to mock to a separate class and mock that class. One logical place for it would be a StepExecutionListener.
https://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/StepExecutionListener.html



Hope this helps....





No sorry to say i do not think it does. I'm trying to just test my job flow before the @Beforestep was introduced it worked perfectly and I was hoping to find a fix for it. But at least you have come to the same conclution I have so that means it is probably the right conclution. Thank you for all your effort! I really appreciate it! You gave me one small idea that might work but I will not test it until wednesday. I will get back to this thread then to tell you how it worked out. Thanks again!
– PlickPlick
Apr 29 at 10:14







@PlickPlick, were you able to solve your issue?
– Maarten
May 7 at 10:14





Nope my ideas was what you descripe above but got stuck with the same result. MockBean and Beforestep does not mix with inheritance. Would be nice if it ever got fixed. I scraped my tests, They were not really nessesary any more. Replaced them with integrationtests instead. But thank you very much for all your feedback! Have been really nice to have someone else come to the same conclution! It means that I could let it go so much faster. Instead of wondering what I did wrong.
– PlickPlick
May 8 at 17:23





No problem. Happy to keep people sane. :-)
– Maarten
May 17 at 8:33



implement stepexecutionlistener interface in your class and override before and after step method this solves my problem dont use @beforestep


public class Reader implements ItemReader<Integer>,StepExecutionListener{

private final Logger logger = LoggerFactory.getLogger(getClass());
private Iterator<Integer> iterator;

@Override
public Integer read() throws UnexpectedInputException, ParseException, NonTransientResourceException {
if(iterator.hasNext()){
return iterator.next();
}
return null;
}

@Override
public void beforeStep(StepExecution stepExecution){
List<Integer> integerList = (List<Integer>)stepExecution.getJobExecution().getExecutionContext().get(CKEY_ERROREVENT_IDS);
this.iterator = integerList.iterator();
}

@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
}






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Makefile test if variable is not empty

Will Oldham

'Series' object is not callable Error / Statsmodels illegal variable name