我在一个上下文文件中配置了两个作业
<batch:job id="JobA" restartable="true">
<batch:step id="abc">
<batch:tasklet >
<batch:chunk reader="reader" writer="writer" processor="processor" />
</batch:tasklet>
</batch:step>
</batch:job>
<batch:job id="JobB" restartable="true">
<batch:step id="abc">
<batch:tasklet >
<batch:chunk reader="reader" writer="writer" processor="processor" />
</batch:tasklet>
</batch:step>
</batch:job>
当我使用JobLauncherTestUtils
对JobA进行单元测试并测试作业启动时,它会抛出一个例外
No unique bean of type [org.springframework.batch.core.Job;] is defined: expected single matching bean but found 2: [JobA, JobB]
我尝试使用@Qualifier
进行autowire仍然是同样的事情。我在哪里做错了
编辑
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:META-INF/spring/batch-test-context.xml" })
public class TestJob {
@Autowired
private JobExplorer jobExplorer;
@Autowired
@Qualifier("JobA")
private Job JobA;
@Autowired
private JobLauncherTestUtils jobLauncherTestUtils;
@Test
public void testJob() throws Exception {
JobParameters jobParameters = getNextJobParameters(getJobParameters());
assertEquals(BatchStatus.COMPLETED, jobLauncherTestUtils.getJobLauncher().run(JobA, jobParameters));
}
private JobParameters getJobParameters() {
JobParametersBuilder jobParameters = new JobParametersBuilder();
jobParameters.addString("param", "123");
return jobParameters.toJobParameters();
}
private JobParameters getNextJobParameters(JobParameters jobParameters) {
String jobIdentifier = jobLauncherTestUtils.getJob().getName();
List<JobInstance> lastInstances = jobExplorer.getJobInstances(jobIdentifier, 0, 1);
JobParametersIncrementer incrementer = jobLauncherTestUtils.getJob().getJobParametersIncrementer();
if (lastInstances.isEmpty()) {
return incrementer.getNext(jobParameters);
} else {
List<JobExecution> lastExecutions = jobExplorer.getJobExecutions(lastInstances.get(0));
return incrementer.getNext(lastExecutions.get(0).getJobParameters());
}
}
}
例外是
No unique bean of type [org.springframework.batch.core.Job;] is defined: expected single matching bean but found 2: [JobA, JobB]`
答案 0 :(得分:5)
也许迟到了,
但我找到了自己的工作解决方案:手动配置JobLauncherTestUtils
:
@Inject
@Qualifier(value = "Job1")
private Job job;
@Inject
private JobLauncher jobLauncher;
@Inject
private JobRepository jobRepository;
private JobLauncherTestUtils jobLauncherTestUtils;
private void initailizeJobLauncherTestUtils() {
this.jobLauncherTestUtils = new JobLauncherTestUtils();
this.jobLauncherTestUtils.setJobLauncher(jobLauncher);
this.jobLauncherTestUtils.setJobRepository(jobRepository);
this.jobLauncherTestUtils.setJob(job);
}
@Before
public void setUp() throws Exception {
this.initailizeJobLauncherTestUtils();
}
使用它可以控制应该应用JobLauncherTestUtils的Job。 (默认情况下,它需要在上下文中单个作业配置)
答案 1 :(得分:2)
您在bean配置文件中声明了两个类似的bean。
要解决上述问题,您需要@Qualifier("JobA")
和@Qualifier("JobB")
告诉Spring哪个bean应自动连接到哪个作业。
答案 2 :(得分:2)
因为在source ~/.bash_profile
的设置器上有一个.zshrc
批注,所以我必须在创建bean之后使用MergedBeanDefinitionPostProcessor来设置属性:
@Autowired
答案 3 :(得分:0)
我通过分别为每个作业创建JobLauncherTestUtils解决了这一问题(常规):
@TestConfiguration class BatchJobTestConfiguration {
@Autowired
@Qualifier('job1')
private Job job1
@Autowired
@Qualifier('job2')
private Job job2
@Autowired
JobRepository jobRepository;
@Bean
JobLauncher jobLauncher() throws Exception {
SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
jobLauncher.setJobRepository(jobRepository);
jobLauncher.setTaskExecutor(new SyncTaskExecutor());
jobLauncher.afterPropertiesSet();
return jobLauncher;
}
@Bean(name = 'jobLauncherTestUtilsJob1')
JobLauncherTestUtils jobLauncherTestUtilsSyncEndUserJob() {
new JobLauncherNoAutowireTestUtil(
job: job1,
jobLauncher: jobLauncher()
)
}
@Bean(name = 'jobLauncherTestUtilsJob2')
JobLauncherTestUtils jobLauncherTestUtilsenewCaseJob() {
new JobLauncherNoAutowireTestUtil(
job: job2,
jobLauncher: jobLauncher()
)
}
然后将其添加到您的测试中:
@ContextConfiguration(classes = [BatchJobTestConfiguration])
...
@Autowired
@Qualifier('jobLauncherTestUtilsJob1')
private JobLauncherTestUtils jobLauncherTestUtils
...
when:
def jobExecution = jobLauncherTestUtils.launchJob()
答案 4 :(得分:0)
无法回答原始问题,但是使用下面的代码,我们避免了在相同类中的测试用例顺序运行期间重复使用JobLauncherTestUtils。
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
这表示Junit在每次运行后都要清理并重建上下文。
答案 5 :(得分:0)
我们面临同样的问题,因为我们在项目中也使用了spring-cloud-configuration
,需要@SpringBootTest
注解,然后加载整个Spring Boot上下文,所以在上下文中加载了多个作业。>
我们得到的解决方案接近于 Ilya Dyoshin 提供的解决方案,使用构造函数注入和 Junit 5:
@ExtendWith(SpringExtension.class)
@SpringBootTest
class MyJobConfigTest {
private final JobLauncherTestUtils jobLauncherTestUtils;
@Autowired
public MyJobConfigTest(Job jobNumber1, JobLauncher jobLauncher, JobRepository jobRepository) {
this.jobLauncherTestUtils = new JobLauncherTestUtils();
this.jobLauncherTestUtils.setJobLauncher(jobLauncher);
this.jobLauncherTestUtils.setJobRepository(jobRepository);
this.jobLauncherTestUtils.setJob(jobNumber1);
}
答案 6 :(得分:0)
使用 Spring Boot 时,我建议使用 @EnableBatchProcessing(modular = true)
然后可以通过仅提供带有 @SpringBootTest(classes = { JobAConfiguration.class, ... })
有一个很棒且全面的示例,其中包括针对 https://github.com/desprez/springbatch-modular 的不同作业的单独测试类(不是我的,向作者致敬)。