如何用Mockito或OOTB API Mock Spring Batch作业编写测试用例?
解决Spring Batch测试中Mock整个作业的问题
老哥,你当前的测试会执行真实作业,本质原因是@SpringBatchTest会自动配置批处理相关的测试组件(比如JobLauncherTestUtils),再加上@SpringBootTest会启动完整的Spring上下文,这就把你的真实Job和Step都实例化加载进来了,自然会触发真实的批处理流程。
下面给你两种可行的方案,既有Spring Boot自带的开箱即用方式,也有用Mockito实现的方法:
方案一:用Spring Boot的@MockBean替换真实Job
Spring Boot的@MockBean注解可以轻松把Spring容器里的真实Job替换成Mock实例,这样JobLauncherTestUtils调用的就是Mock的Job,完全不会触发真实执行。
修改后的测试代码如下:
@SpringBatchTest @SpringBootTest @RunWith(SpringRunner.class) public class JobTest { @Autowired private JobLauncherTestUtils jobLauncherTestUtils; // 用@MockBean替换容器中的真实Job,这里替换成你项目里实际的Job类名 @MockBean private Job yourActualJob; @Before public void setUp() throws Exception { // 用Spring Batch自带的工具类创建模拟的JobExecution JobExecution mockJobExecution = MetaDataInstanceFactory.createJobExecution(); mockJobExecution.setStatus(BatchStatus.COMPLETED); // 模拟StepExecution的结果 StepExecution mockStepExecution = MetaDataInstanceFactory.createStepExecution(); mockStepExecution.setStatus(BatchStatus.COMPLETED); mockJobExecution.addStepExecution(mockStepExecution); // 让Mock Job返回我们模拟好的执行结果 when(yourActualJob.execute(any(JobParameters.class))).thenReturn(mockJobExecution); } @Test public void testJobCompletion() throws Exception { JobExecution jobExecution = jobLauncherTestUtils.launchJob(); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); } }
方案二:手动配置测试组件,避免加载完整批处理上下文
如果你不想加载完整的Spring Batch上下文,可以去掉@SpringBatchTest,手动创建JobLauncherTestUtils并注入Mock的Job和JobLauncher:
@SpringBootTest(classes = {TestConfig.class}) @RunWith(SpringRunner.class) public class JobTest { @Autowired private JobLauncherTestUtils jobLauncherTestUtils; // 内部配置类,只加载测试需要的组件 @Configuration static class TestConfig { @Bean public JobLauncher jobLauncher() { return mock(JobLauncher.class); } @Bean public Job yourActualJob() { return mock(Job.class); } @Bean public JobLauncherTestUtils jobLauncherTestUtils() throws Exception { JobLauncherTestUtils testUtils = new JobLauncherTestUtils(); testUtils.setJob(yourActualJob()); testUtils.setJobLauncher(jobLauncher()); return testUtils; } } @Before public void setUp() throws Exception { JobExecution mockJobExecution = MetaDataInstanceFactory.createJobExecution(); mockJobExecution.setStatus(BatchStatus.COMPLETED); StepExecution mockStepExecution = MetaDataInstanceFactory.createStepExecution(); mockStepExecution.setStatus(BatchStatus.COMPLETED); mockJobExecution.addStepExecution(mockStepExecution); // 模拟JobLauncher的launch方法返回我们预设的结果 when(jobLauncherTestUtils.getJobLauncher().launch(any(Job.class), any(JobParameters.class))) .thenReturn(mockJobExecution); } @Test public void testJobCompletion() throws Exception { JobExecution jobExecution = jobLauncherTestUtils.launchJob(); assertEquals(BatchStatus.COMPLETED, jobExecution.getStatus()); StepExecution stepExecution = jobExecution.getStepExecutions().iterator().next(); assertEquals(BatchStatus.COMPLETED, stepExecution.getStatus()); } }
额外小提示
- 两种方案的核心都是把真实的Job/JobLauncher换成Mock实例,从根源上避免触发真实批处理逻辑。
MetaDataInstanceFactory是Spring Batch官方提供的工具类,能快速创建模拟的JobExecution和StepExecution,省得你手动去设置一堆属性。- 如果你还想验证Job是否被正确调用,可以加一句
verify(yourActualJob).execute(any(JobParameters.class)),这样就能确认Mock的Job确实被触发了。
内容的提问来源于stack exchange,提问作者Jeff Cook
相关产品推荐
相关产品推荐

