Search code examples
spring-bootspring-batchspring-boot-test

Error creating bean with name 'jobLauncherTestUtils': Unsatisfied dependency expressed through method 'setJob'


I have a Job configured to read data from one database and write on another. My JobConfiguration has a Job bean with this configuration:

@Configuration
@EnableBatchProcessing
public class JobConfiguration {
    private static final String JOB_NAME = "loadCompanyCountryJob";
    private static final String STEP_NAME = "loadCompanyCountryStep";
    private static final int CHUNK_COMMIT_SIZE = 100;

    @Bean
    public Job job(JobBuilderFactory jobBuilderFactory,
                   StepBuilderFactory stepBuilderFactory,
                   ItemReader<SourceEntity> itemReader,
                   ItemProcessor<SourceEntity, DestinationEntity> itemProcessor,
                   ItemWriter<DestinationEntity> itemWriter
    ) {
        Step step = stepBuilderFactory.get(STEP_NAME)
                .<SourceEntity, DestinationEntity>chunk(CHUNK_COMMIT_SIZE)
                .reader(itemReader)
                .processor(itemProcessor)
                .writer(itemWriter)
                .build();
        return jobBuilderFactory.get(JOB_NAME)
                .incrementer(new RunIdIncrementer())
                .start(step)
                .build();
    }

}

Now I want to create a test class to this Job:

@ExtendWith(SpringExtension.class)
@SpringBatchTest
@EnableAutoConfiguration
@ContextConfiguration(classes = JobConfiguration.class)
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
        DirtiesContextTestExecutionListener.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public class SpringBatchJobTest {

    @Autowired
    private JobLauncherTestUtils jobLauncherTestUtils;

    @Autowired
    private JobRepositoryTestUtils jobRepositoryTestUtils;

    @Before
    public void clearJobExecutions() {
        this.jobRepositoryTestUtils.removeJobExecutions();
    }

    @Test
    public void givenReferenceOutput_whenJobExecuted_thenSuccess() throws Exception {
        // given
        JobParameters jobParameters = this.jobLauncherTestUtils.getUniqueJobParameters();

        // when
        JobExecution jobExecution = this.jobLauncherTestUtils.launchJob(jobParameters);
        JobInstance actualJobInstance = jobExecution.getJobInstance();
        ExitStatus actualJobExitStatus = jobExecution.getExitStatus();

        // then
        Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
    }
....

But when I try to start the test I'm facing an error:

Caused by: Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'job' defined in com.closeupinternational.cpoprocessbatch.job.JobConfiguration: Unsatisfied dependency expressed through method 'job' parameter 2; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.batch.item.ItemReader<com.closeupinternational.cpoprocessbatch.data.source.SourceEntity>' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

How can I create a test to this job? I'm using a H2 database to simulate the database.


Solution

  • I've changed the implementation of JobConfiguration:

        @Bean
        public Job job(JobBuilderFactory jobBuilderFactory, StepBuilderFactory stepBuilderFactory
        ) {
            log.info("Called job configuration");
            return jobBuilderFactory.get(JOB_NAME)
                    .incrementer(new RunIdIncrementer())
                    .start(loadCompanyCountryStep(stepBuilderFactory))
                    .build();
        }
    
        @Bean
        public Step loadCompanyCountryStep(StepBuilderFactory stepBuilderFactory){
            log.info("Called step configuration");
            return stepBuilderFactory.get(STEP_NAME)
                    .<SourceEntity, DestinationEntity>chunk(CHUNK_COMMIT_SIZE)
                    .reader(reader())
                    .processor(processor())
                    .writer(writer())
                    .build();
        }
    
        @Bean
        public CompanyCountryItemReader reader() {
            log.info("Creating an CompanyCountryItemReader");
            return new CompanyCountryItemReader();
        }
    
        @Bean
        public CompanyCountryItemProcessor processor() {
            log.info("Creating an CompanyCountryItemProcessor");
            return new CompanyCountryItemProcessor();
        }
    
        @Bean
        public CompanyCountryItemWriter writer() {
            log.info("Creating an CompanyCountryItemWriter");
            return new CompanyCountryItemWriter();
        }