使用@MockBean使用@BeforeStep模拟ItemReader使用@Beforestep anotation将许多方法抛出异常。我该如何解决?

时间:2018-04-24 09:43:04

标签: java annotations spring-batch applicationcontext

我有自己的ItemReader实现,有两种方法。

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

当我尝试在spring-batch上下文中运行它并使用@MockBean模拟ItemReader时,应用程序上下文将抛出:

  

java.lang.IllegalArgumentException:在目标类[Reader $ MockitoMock $ 368106910]上找到了多个注释类型为[BeforeStep]的方法。

以下是我开始工作的方式。

@MockBean
private Reader reader;

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

4 个答案:

答案 0 :(得分:1)

我已经能够重现您的问题。之后,我用你读者的子类替换了模拟。

@Component
public class ChildReader extends Reader{

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

这给出了同样的例外。 在运行时,Mockito还创建了Reader的子类。我认为这会导致你的问题。

在这篇文章中,描述了同样的问题: http://forum.spring.io/forum/spring-projects/batch/98067-beforestep-in-abstract-class 我找不到任何有关修复的提法。

解决此问题的方法是将要模拟的代码提取到单独的类并模拟该类。一个合乎逻辑的地方是StepExecutionListener。 https://docs.spring.io/spring-batch/trunk/apidocs/org/springframework/batch/core/StepExecutionListener.html

希望这会有所帮助......

答案 1 :(得分:0)

在您的类中实现stepexecutionlistener接口,并覆盖step方法之前和之后,这解决了我的问题,请勿使用@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;
    }   
}

答案 2 :(得分:0)

如果将MockBean更改为接口,应该修复

代替

@MockBean
private Reader reader;

@MockBean
private ItemReader<Integer> reader;

如果要嘲笑它,则不需要具体类的内容。

答案 3 :(得分:0)

对我来说,它可以使用mock(ClassToBeMocked.class)代替@MockBean