使用@MockBean 模拟带有@BeforeStep 的ItemReader 会向带有@Beforestep 注释的许多方法抛出异常。我该如何解决?

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

我有自己的 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 批处理上下文中 运行 并使用 @MockBean 模拟 ItemReader 时,应用程序上下文抛出:

java.lang.IllegalArgumentException: found more than one method on target class [Reader$MockitoMock8106910] with the annotation type [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);
}

我已经能够重现您的问题。在那之后,我用你的 Reader.

的 child class 替换了模拟
@Component
public class ChildReader extends Reader{

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

这给出了同样的例外。 在运行时,Mockito 还会创建 Reader 的 subclass。我认为这是导致您的问题的原因。

在此 post 中,描述的是同一问题: http://forum.spring.io/forum/spring-projects/batch/98067-beforestep-in-abstract-class 我找不到任何关于它被修复的参考。

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

希望这对您有所帮助....

在你的 class 中实现 stepexecutionlistener 接口并重写 before 和 after 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;
    }   
}

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

而不是

@MockBean
private Reader reader;

@MockBean
private ItemReader<Integer> reader;

如果你正在模拟它,你不应该需要你的具体 class 的内容。

对我来说,使用 mock(ClassToBeMocked.class) 而不是 @MockBean!