如何成功加载 JobLauncherTestUtils class 用于 Spring 任务用于 Spring 批处理 JUnit 5 测试
How to successfullky load the JobLauncherTestUtils class for a Spring Task for a Spring Batch JUnit 5 Test
我有这个看似简单的配置用于 spring 批量测试。但是,测试无法加载上下文。该错误告诉我存在与数据源相关的无法解析的循环引用。如果我删除数据源,则错误会更改为尚未定义数据源。我想要实现的是能够加载 JobLauncherTestUtils,然后启动一个作业来测试这些步骤。这看起来很简单,但要加载一个简单的测试作业却非常困难。我是 运行 spring boot 2 on Java 12 and spring 5 and spring batch 2.2.0.RELEASE and JUnit 5 (Jupiter)。配置有什么问题?我需要做哪些改变。我认为您不一定必须指定数据源配置,但如果不配置一个,它根本就不会接近加载。这是我的配置。如果能帮我找出我的配置有什么问题,我将不胜感激。我的 objective 只是为了成功自动装配 JobLauncherTestUtils class.
like
class BatchTest {
@Autowired
JobLauncherTestUtils jobLauncherTestUtils;
}
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@SpringBatchTest
@ContextConfiguration(classes = {BatchTest.BatchConfiguration.class,
BatchAutoConfiguration.class})
@TestPropertySource(properties = "debug=true")
public class BatchTest {
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void test() {
this.jobLauncherTestUtils.launchStep("orderProcessingJob");
//assertions
}
@Configuration
@EnableBatchProcessing
public static class BatchConfiguration {
private JobBuilderFactory jobBuilderFactory;
@Bean(name="jobLauncherTestUtils")
public JobLauncherTestUtils jobLauncherTestUtils() throws Exception {
JobLauncherTestUtils jl = new JobLauncherTestUtils();
jl.setJobLauncher(jobLauncher());
jl.setJob(orderProcessorJob());
jl.setJobRepository(jobRepository().getObject());
return jl;
}
@Bean
public JobRepositoryFactoryBean jobRepository() {
JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
jobRepositoryFactoryBean.setDataSource(dataSource());
return jobRepositoryFactoryBean;
}
@Bean
public Job orderProcessorJob() {
return jobBuilderFactory.get("orderProcessingJob")
.incrementer(new RunIdIncrementer())
.flow(orderIntakeStep())
.end()
.build();
}
private Step orderIntakeStep() {
// code for order Intake
}
@Bean
public JobLauncher jobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository().getObject());
return jobLauncher;
}
private StepBuilderFactory stepBuilderFactory;
@Bean
public EmbeddedDatabase dataSource() {
return new EmbeddedDatabaseBuilder().build();
}
@Autowired
public BatchConfiguration(JobBuilderFactory jobBuilderFactory ,
StepBuilderFactory stepBuilderFactory) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
}
}
}
这是我看到的堆栈跟踪的核心部分:
原因:org.springframework.beans.factory.UnsatisfiedDependencyException:创建名称为 'batchTest.BatchConfiguration' 的 bean 时出错:
通过构造函数参数 0 表达的不满足的依赖关系;嵌套异常
是 org.springframework.beans.factory.UnsatisfiedDependencyException:创建名称为 'org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration' 的 bean 时出错:
通过字段 'dataSource' 表示的未满足的依赖关系;嵌套异常是 org.springframework.beans.factory.BeanCurrentlyInCreationException:
创建名为 'batchTest.BatchConfiguration' 的 bean 时出错:当前正在创建请求的 bean:是否存在无法解析的循环引用?
Unsatisfied dependency expressed through field 'dataSource'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'batchTest.BatchConfiguration': Requested bean is currently in creation: Is there an unresolvable circular reference?
您尝试在 BatchConfiguration#jobRepository()
中注入的数据源正在同一 class(dataSource()
方法)中创建,因此出现错误。您需要在单独的 class 中提取数据源配置,例如:
@Configuration
public static class DataSourceConfig {
@Bean
public EmbeddedDatabase dataSource() {
return new EmbeddedDatabaseBuilder().build();
}
}
然后将其导入您的 BatchConfiguration
:
@Configuration
@Import(DataSourceConfig.class)
@EnableBatchProcessing
public static class BatchConfiguration {
// ..
@Bean
public JobRepositoryFactoryBean jobRepository(DataSource dataSource) {
JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
jobRepositoryFactoryBean.setDataSource(dataSource);
return jobRepositoryFactoryBean;
}
// ..
}
我建议将基础结构 bean 与业务逻辑 bean 分开。也就是说,由于您使用的是 @EnableBatchProcessing
,因此无需自行配置作业存储库、作业启动器等。此注释的目标是为您提供那些基础结构 bean,请参阅 its javadoc。
My objective is simply to successfully autowire the JobLauncherTestUtils class.
由于您使用的是 @SpringBatchTest
,因此无需手动创建 JobLauncherTestUtils
(在您的 jobLauncherTestUtils()
方法中),此注释的目的是为您导入它,参见 its Javadoc。这是一个典型的用法:
@RunWith(SpringRunner.class)
@SpringBatchTest
@ContextConfiguration(classes = MyBatchJobConfiguration.class)
public class MyBatchJobTests {
@@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@@Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
@Before
public void clearJobExecutions() {
this.jobRepositoryTestUtils.removeJobExecutions();
}
@Test
public void testMyJob() throws Exception {
// given
JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
// when
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
// then
Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}
我有这个看似简单的配置用于 spring 批量测试。但是,测试无法加载上下文。该错误告诉我存在与数据源相关的无法解析的循环引用。如果我删除数据源,则错误会更改为尚未定义数据源。我想要实现的是能够加载 JobLauncherTestUtils,然后启动一个作业来测试这些步骤。这看起来很简单,但要加载一个简单的测试作业却非常困难。我是 运行 spring boot 2 on Java 12 and spring 5 and spring batch 2.2.0.RELEASE and JUnit 5 (Jupiter)。配置有什么问题?我需要做哪些改变。我认为您不一定必须指定数据源配置,但如果不配置一个,它根本就不会接近加载。这是我的配置。如果能帮我找出我的配置有什么问题,我将不胜感激。我的 objective 只是为了成功自动装配 JobLauncherTestUtils class.
like
class BatchTest {
@Autowired
JobLauncherTestUtils jobLauncherTestUtils;
}
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.launch.support.SimpleJobLauncher;
import org.springframework.batch.core.repository.support.JobRepositoryFactoryBean;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.batch.BatchAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabase;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
@ExtendWith(SpringExtension.class)
@SpringBatchTest
@ContextConfiguration(classes = {BatchTest.BatchConfiguration.class,
BatchAutoConfiguration.class})
@TestPropertySource(properties = "debug=true")
public class BatchTest {
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void test() {
this.jobLauncherTestUtils.launchStep("orderProcessingJob");
//assertions
}
@Configuration
@EnableBatchProcessing
public static class BatchConfiguration {
private JobBuilderFactory jobBuilderFactory;
@Bean(name="jobLauncherTestUtils")
public JobLauncherTestUtils jobLauncherTestUtils() throws Exception {
JobLauncherTestUtils jl = new JobLauncherTestUtils();
jl.setJobLauncher(jobLauncher());
jl.setJob(orderProcessorJob());
jl.setJobRepository(jobRepository().getObject());
return jl;
}
@Bean
public JobRepositoryFactoryBean jobRepository() {
JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
jobRepositoryFactoryBean.setDataSource(dataSource());
return jobRepositoryFactoryBean;
}
@Bean
public Job orderProcessorJob() {
return jobBuilderFactory.get("orderProcessingJob")
.incrementer(new RunIdIncrementer())
.flow(orderIntakeStep())
.end()
.build();
}
private Step orderIntakeStep() {
// code for order Intake
}
@Bean
public JobLauncher jobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository().getObject());
return jobLauncher;
}
private StepBuilderFactory stepBuilderFactory;
@Bean
public EmbeddedDatabase dataSource() {
return new EmbeddedDatabaseBuilder().build();
}
@Autowired
public BatchConfiguration(JobBuilderFactory jobBuilderFactory ,
StepBuilderFactory stepBuilderFactory) {
this.jobBuilderFactory = jobBuilderFactory;
this.stepBuilderFactory = stepBuilderFactory;
}
}
}
这是我看到的堆栈跟踪的核心部分:
原因:org.springframework.beans.factory.UnsatisfiedDependencyException:创建名称为 'batchTest.BatchConfiguration' 的 bean 时出错:
通过构造函数参数 0 表达的不满足的依赖关系;嵌套异常
是 org.springframework.beans.factory.UnsatisfiedDependencyException:创建名称为 'org.springframework.batch.core.configuration.annotation.SimpleBatchConfiguration' 的 bean 时出错:
通过字段 'dataSource' 表示的未满足的依赖关系;嵌套异常是 org.springframework.beans.factory.BeanCurrentlyInCreationException:
创建名为 'batchTest.BatchConfiguration' 的 bean 时出错:当前正在创建请求的 bean:是否存在无法解析的循环引用?
Unsatisfied dependency expressed through field 'dataSource'; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'batchTest.BatchConfiguration': Requested bean is currently in creation: Is there an unresolvable circular reference?
您尝试在 BatchConfiguration#jobRepository()
中注入的数据源正在同一 class(dataSource()
方法)中创建,因此出现错误。您需要在单独的 class 中提取数据源配置,例如:
@Configuration
public static class DataSourceConfig {
@Bean
public EmbeddedDatabase dataSource() {
return new EmbeddedDatabaseBuilder().build();
}
}
然后将其导入您的 BatchConfiguration
:
@Configuration
@Import(DataSourceConfig.class)
@EnableBatchProcessing
public static class BatchConfiguration {
// ..
@Bean
public JobRepositoryFactoryBean jobRepository(DataSource dataSource) {
JobRepositoryFactoryBean jobRepositoryFactoryBean = new JobRepositoryFactoryBean();
jobRepositoryFactoryBean.setDataSource(dataSource);
return jobRepositoryFactoryBean;
}
// ..
}
我建议将基础结构 bean 与业务逻辑 bean 分开。也就是说,由于您使用的是 @EnableBatchProcessing
,因此无需自行配置作业存储库、作业启动器等。此注释的目标是为您提供那些基础结构 bean,请参阅 its javadoc。
My objective is simply to successfully autowire the JobLauncherTestUtils class.
由于您使用的是 @SpringBatchTest
,因此无需手动创建 JobLauncherTestUtils
(在您的 jobLauncherTestUtils()
方法中),此注释的目的是为您导入它,参见 its Javadoc。这是一个典型的用法:
@RunWith(SpringRunner.class)
@SpringBatchTest
@ContextConfiguration(classes = MyBatchJobConfiguration.class)
public class MyBatchJobTests {
@@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@@Autowired
private JobRepositoryTestUtils jobRepositoryTestUtils;
@Before
public void clearJobExecutions() {
this.jobRepositoryTestUtils.removeJobExecutions();
}
@Test
public void testMyJob() throws Exception {
// given
JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();
// when
JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
// then
Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
}