测试弹簧批处理作业会导致意外结果

时间:2019-08-30 12:18:22

标签: java spring spring-batch integration-testing testing-strategies

我正在尝试创建一个简单的备份作业处理程序,以验证我的目标是否正确。

我正在尝试使用春季批测试进行结果验证。

PS我的批处理使用框架提供的非默认配置,因为我们的作业存储库应使用非默认架构名称。

我的工作的读取步骤配置为使用@StepScope批注进行延迟初始化,这是必需的,因为我的工作应具有一些参数以在读取步骤中查询数据库

这是我们正在使用的示例配置 它在根包中,其余批处理配置位于子包中

@Configuration
@Import({ApplicationHibernateConfiguration.class})
@ComponentScan
public class ApplicationBatchConfiguration extends DefaultBatchConfigurer {

    private static final String BATCH_PROCESSING_PREFIX = "BATCH_PROCESSING.BATCH_";
    private final DataSource dataSource;
    private final PlatformTransactionManager transactionManager;
    private final JobLauncher jobLauncher;
    private final JobRepository jobRepository;
    private final JobExplorer jobExplorer;

    @Autowired
    public GlobalLogisticsPortalBatchConfiguration(
            DataSource dataSource, PlatformTransactionManager transactionManager) throws Exception {
        this.dataSource = dataSource;
        this.transactionManager = transactionManager;
        this.jobRepository = createJobRepository();
        this.jobLauncher = createJobLauncher();
        this.jobExplorer = createJobExplorer();
    }


    @Override
    protected JobLauncher createJobLauncher() throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository);
        jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
        jobLauncher.afterPropertiesSet();
        return jobLauncher;
    }

    @Override
    protected JobRepository createJobRepository() throws Exception {
        JobRepositoryFactoryBean factoryBean = new JobRepositoryFactoryBean();
        factoryBean.setDatabaseType("DB2");
        factoryBean.setTablePrefix(BATCH_PROCESSING_PREFIX);
        factoryBean.setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ");
        factoryBean.setDataSource(this.dataSource);
        factoryBean.setTransactionManager(this.transactionManager);
        factoryBean.afterPropertiesSet();
        return factoryBean.getObject();
    }

    @Override
    protected JobExplorer createJobExplorer() throws Exception {
        JobExplorerFactoryBean factoryBean = new JobExplorerFactoryBean();
        factoryBean.setDataSource(this.dataSource);
        factoryBean.setTablePrefix(BATCH_PROCESSING_PREFIX);
        factoryBean.afterPropertiesSet();
        return factoryBean.getObject();
    }

    @Override
    @Bean
    public JobRepository getJobRepository() {
        return jobRepository;
    }

    @Override
    public PlatformTransactionManager getTransactionManager() {
        return transactionManager;
    }

    @Override
    @Bean
    public JobLauncher getJobLauncher() {
        return jobLauncher;
    }

    @Override
    @Bean
    public JobExplorer getJobExplorer() {
        return jobExplorer;
    }

    @Bean
    public JobBuilderFactory jobBuilderFactory(JobRepository jobRepository) {
        return new JobBuilderFactory(jobRepository);
    }

    @Bean
    public StepBuilderFactory stepBuilderFactory(
            JobRepository jobRepository, PlatformTransactionManager transactionManager) {
        return new StepBuilderFactory(jobRepository, transactionManager);
    }


}

我尝试使用的步骤如下:

    @Bean
    @StepScope
    public JdbcPagingItemReader<DomainObject> itemReader(
            @Value("#{jobParameters['id']}") String id) {
        JdbcPagingItemReader<DomainObject> reader = new JdbcPagingItemReader<>();
        reader.setDataSource(this.dataSource);
        reader.setFetchSize(10);
        Db2PagingQueryProvider nativeQueryProvider = new Db2PagingQueryProvider();
        nativeQueryProvider.setSelectClause("*");
        nativeQueryProvider.setFromClause("from SCHEMA.DOMAIN");
        nativeQueryProvider.setWhereClause("id = :id");
        Map<String, Object> params = new HashMap<>(1);
        params.put("id", id);
        reader.setRowMapper((rs, rowNum) -> {
            DomainObject element = new DomainObject();
            element.setId(rs.getString("ID"));
            return element;
        });
        reader.setParameterValues(params);
        reader.setQueryProvider(nativeQueryProvider);
        return reader;
    }

    @Bean
    public Step fetchDomain() throws Exception {
        return stepBuilderFactory.get("fetchDomain")
                .<HierarchyElement, HierarchyElement>chunk(10)
                .faultTolerant()
                .reader(itemReader(null))
                .writer(items -> items.forEach(System.out::println))
                .build();
    }

实际的作业bean当前已配置为仅启动单个步骤

    @Bean
    public Job backupJob() throws Exception {
        return jobBuilderFactory.get("backupJob")
                .start(fetchHeid())
                .build();
    }

我的测试代码如下

@RunWith(SpringRunner.class)
@SpringBatchTest
@ContextConfiguration(classes = {ApplicationBatchConfiguration.class})
public class BackupJobConfigurationTest {
    @Autowired
    @Qualifier(value = "backupJob")
    public Job job;

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    @Test
    public void flowTest() throws Exception {
        JobParameters parameters = new JobParametersBuilder()
                .addString("id", "124")
                .toJobParameters();

        JobExecution execution = jobLauncherTestUtils.launchJob(parameters);

        assertEquals(BatchStatuses.COMPLETED, execution.getExitStatus().getExitCode()); //failed
    }
}

我希望退出代码为“ COMPLETED”,并得到“ UNKNOWN”。 另外我不确定代码实际上是否被调用,因为我看不到编写器lambda的任何输出。

我在测试中看到的唯一输出是

Aug 30, 2019 2:52:17 PM org.springframework.batch.core.launch.support.SimpleJobLauncher run
INFO: Job: [FlowJob: [name=backupJob]] launched with the following parameters: [{id=124}]

org.junit.ComparisonFailure: 
Expected :COMPLETED
Actual   :UNKNOWN

1 个答案:

答案 0 :(得分:0)

我知道,首先,我需要从配置中删除SimpleAsyncTaskExecutor才能在同一线程中实际测试代码,然后通过更仔细地阅读参考资料,我重新配置了批处理配置,而不是扩展直接将BatchConfigurer配置为我的配置中的bean,并添加@EnableSpringBatch批注

    @Bean
    public BatchConfigurer batchConfigurer() {
    return new DefaultBatchConfigurer() {
        @Override
        protected JobRepository createJobRepository() throws Exception {
            JobRepositoryFactoryBean factoryBean = new JobRepositoryFactoryBean();
            factoryBean.setDatabaseType("db2");
            factoryBean.setTablePrefix(BATCH_PROCESSING_PREFIX);
            factoryBean.setIsolationLevelForCreate("ISOLATION_REPEATABLE_READ");
            factoryBean.setDataSource(dataSource);
            factoryBean.setTransactionManager(transactionManager);
            factoryBean.afterPropertiesSet();
            return factoryBean.getObject();
        }

        @Override
        protected JobExplorer createJobExplorer() throws Exception {
            JobExplorerFactoryBean factoryBean = new JobExplorerFactoryBean();
            factoryBean.setDataSource(dataSource);
            factoryBean.setTablePrefix(BATCH_PROCESSING_PREFIX);
            factoryBean.afterPropertiesSet();
            return factoryBean.getObject();
        }

        @Override
        protected JobLauncher createJobLauncher() throws Exception {
            SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
            jobLauncher.setJobRepository(getJobRepository());
            //jobLauncher.setTaskExecutor(new SimpleAsyncTaskExecutor());
            jobLauncher.afterPropertiesSet();
            return jobLauncher;
        }
    };
}
相关问题