我有一个spring批处理项目。目标是对spring作业中存在的各个步骤执行集成测试。
我正在使用joblaunchertestutils启动步骤。但是,当这个util启动这些步骤时,它会在一个单独的线程中运行它。一旦线程完成执行,就应该为其分配一些值 jobExecution.getStepExecutions()
.
问题:由于某种原因,即使在线程完成执行之前,测试也会转到下一行 List<StepExecution> actualStepExecutions = new ArrayList<>(jobExecution.getStepExecutions())
,在哪里 jobExecution.getStepExecutions()
当前为空,因此测试失败 NullPointerException
以及 Index 0 out of bounds for length 0
-标记在下面的测试类中。
问题:有没有合适的方法来等待步骤执行线程完成,然后转到测试中的下一行进行验证?
代码:
集成测试类:
@Slf4j
@SpringBatchTest
@SpringBootTest
@ActiveProfiles({"test", "master"})
@ContextConfiguration(classes = {InhouseClass3.class, InhouseClass1.class, InhouseClass2.class})
public class BatchJobIntegrationTest {
private static final String Param1 = "someParam";
@Autowired
@Qualifier("hikariDatasource")
DataSource hikariDatasource;
@Autowired
Job BatchJob;
@Autowired
JobLauncher jobLauncher;
JobExecution jobExecution;
@Autowired
CreateDirectoryTasklet createDirectoryTasklet;
JobParameters jobParameters;
JobLauncherTestUtils jobLauncherTestUtils;
@BeforeEach
void setUp() {
String startTimestamp = Timestamp.from(Instant.now()).toString();
jobParameters = new JobParametersBuilder()
.addString(Param1, startTimestamp)
.toJobParameters();
jobLauncherTestUtils = new JobLauncherTestUtils();
jobLauncherTestUtils.setJob(BatchJob);
jobLauncherTestUtils.setJobLauncher(jobLauncher);
}
@SneakyThrows
@Test
void TaskletToTest_Test() {
jobExecution = jobLauncherTestUtils.launchStep("loadTaskletToTest", jobParameters);
List<StepExecution> actualStepExecutions = new ArrayList<>(jobExecution.getStepExecutions());
// ERROR: jobExecution.getStepExecutions() is NULL.
ExitStatus actualJobExitStatus = actualStepExecutions.get(0).getExitStatus();
// ERROR: Index 0 out of bounds for length 0
assertEquals("loadGdxClaims", actualStepExecutions.get(0).getStepName());
assertEquals(ExitStatus.COMPLETED, actualJobExitStatus);
}
@SneakyThrows
@Test
// This is my workaround to make my above test run.
// I added a sleep for 2 seconds. But this doesn't look like an ideal way, coz what
// if the launchstep thread running the tasklet took more than 2 seconds?
void loadGDXClaimTaskletTest_Working_() {
jobExecution = jobLauncherTestUtils.launchStep("createDirectory", jobParameters);
boolean counter = true;
while(counter) {
if (jobExecution.getStepExecutions().size()!=0 ) {
List<StepExecution> actualStepExecutions = new ArrayList<>(jobExecution.getStepExecutions());
ExitStatus actualJobExitStatus = actualStepExecutions.get(0).getExitStatus();
log.info("------- step executions : {}", actualStepExecutions);
assertEquals("createDirectory", actualStepExecutions.get(0).getStepName());
assertEquals(ExitStatus.COMPLETED, actualJobExitStatus);
counter = false;
} else {
TimeUnit.SECONDS.sleep(2);
}
}
}
}
要测试的tasklet步骤:
@Slf4j
@Component
public class TaskletToTest implements Tasklet {
private final InhouseService inhouseService;
public TaskletToTest(InhouseService inhouseService) {
this.inhouseService = inhouseService;
}
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws InterruptedException, IllegalJobNameException, JSchException, IOException {
log.info("TaskletToTest before");
inhouseService.retry();
log.info("TaskletToTest after");
return RepeatStatus.FINISHED;
}
}
包含需要测试的步骤列表的批处理作业:
@Slf4j
@Profile("master")
@Configuration
public class MasterConfig extends DefaultBatchConfigurer {
@Bean(name = "BatchJob")
public Job remoteChunkingJob(TaskletStep someOtherTasklet,
TaskletStep loadTaskletToTest,
JobExecutionListener jobExecutionListener) {
return this.jobBuilderFactory.get("extract gdx load")
.incrementer(new RunIdIncrementer())
.listener(jobExecutionListener)
.start(someOtherTasklet)
.next(loadTaskletToTest)
.build();
}
@Bean
TaskletStep loadTaskletToTest(TaskletToTest taskletToTest) {
return this.stepBuilderFactory.get("loadTaskletToTest").tasklet(taskletToTest).build();
}
}
1条答案
按热度按时间yrefmtwq1#
我正在使用joblaunchertestutils启动步骤。但是,当这个util启动这些步骤时,它会在一个单独的线程中运行它。
问题:由于某种原因,即使在线程完成执行之前,测试也会转到下一行
JobLauncherTestUtils
使用JobLauncher
启动作业和步骤。所以取决于JobLauncher
在您使用的实现中,可以在当前线程或单独的线程中运行作业/步骤。你没有分享哪个
JobLauncher
在测试中是自动连接的,但是您似乎已经定义了一个基于异步TaskExecutor
实施。这就是为什么在后台执行作业/步骤的原因:所以你需要检查一下
JobLauncher
(通常为SimpleJobLauncher
使用同步或异步TaskExecutor
)在你的测试中是自动连线的。