无法从JUNIT加载应用程序上下文以进行春季批处理作业



我在春季批处理测试中加载应用程序上下文时遇到了困难。我推荐了春季文档https://docs.spring.io/spring-batch/trunk/reference/html/testing.html以及我在网上可以找到的所有可用信息,但仍然无法获得简单的Junit测试工作。

我正在使用注释加载应用程序上下文,下面的代码。我的目的是能够测试单个步骤。

我还从Web中克隆了一些示例,但是当我在本地计算机中运行时,它们会给我同样的错误 - 无法加载应用程序上下文...这使我思考这些测试应该如何运行?运行为 -> junit测试是所有单元测试如何运行...不是吗?

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {BatchProcessingConfiguration.class, RestTemplateConfig.class, SftpConfig.class, DbConfig.class, RuntimeSessionFactoryLocator.class}, 
                      loader = AnnotationConfigContextLoader.class)
public class BatchProcessingJobApplicationTests extends AbstractTransactionalJUnit4SpringContextTests {
   @Autowired
   private JobLauncherTestUtils jobLauncherTestUtils;
   @Bean
   public DataSource dataSource() {
      DriverManagerDataSource dataSource = new DriverManagerDataSource();
      dataSource.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
      dataSource.setUrl("url");
      dataSource.setUsername("username");
      dataSource.setPassword("password");
      return dataSource;
   }

   @Test
   public void testJob() throws Exception {
      JobExecution jobExecution = jobLauncherTestUtils.launchJob();
      Assert.assertEquals("COMPLETED", jobExecution.getExitStatus().getExitCode());
   }

}

代码来自春季文档。

我是这些东西的新手。感谢您的帮助。

stacktrace:

java.lang.IllegalStateException: Failed to load ApplicationContext 
   at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) 
   at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) 

......

工作代码:

 @RunWith(SpringRunner.class)
    @SpringBatchTest
    @ContextConfiguration(classes = {BatchProcessingJobApplication.class, DataSourceConfiguration.class, JobconfigurationTest.class, BatchProperties.class}, initializers=ConfigFileApplicationContextInitializer.class)
    @ActiveProfiles("test")
    public class BatchProcessingJobApplicationTests {
       @Autowired
       private JobLauncherTestUtils jobLauncherTestUtils;
    @Test
public void testStep() throws Exception {
    // given
    JobParameters jobParameters = jobLauncherTestUtils.getUniqueJobParameters();
    // when
    JobExecution jobExecution = jobLauncherTestUtils.launchStep("jobName", jobParameters);
    // then
    Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
}
    }

    public class DataSourceConfiguration {
    @Bean
        public DataSource dataSource(){
            SQLServerConnectionPoolDataSource dataSource = new SQLServerConnectionPoolDataSource();
              dataSource.setURL(url);
              dataSource.setUser(username);
              dataSource.setPassword(password);
              return dataSource;
        }
    }
    @Configuration
    public class JobconfigurationTest {
          @Bean
          public JobLauncherTestUtils jobLauncherTestUtils() {
                return new JobLauncherTestUtils();
          }
    }

希望这对像我这样的人有帮助。

我的目的是能够测试单个步骤。

您可以使用JobLauncherTestUtils#launchStep(String stepName)来启动特定步骤,而不是整个工作。如果要单元测试特定步骤,我建议仅导入测试步骤所需的配置(我指的是RestTemplateConfigSftpConfig等,除非该步骤确实需要这些)。

请注意,在测试上下文中应将正在测试的作业声明为BEAN,因为它是在JobLauncherTestUtils中自动进行的。就您而言,我认为它是在BatchProcessingConfiguration类中定义的。

典型的步骤测试将是:

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.batch.test.context.SpringBatchTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBatchTest
@ContextConfiguration(classes = {JobConfiguration.class}) // contains the job/step definition
public class JobTest {
   @Autowired
   private JobLauncherTestUtils jobLauncherTestUtils;
   @Test
   public void testStep() throws Exception {
      // given
      JobParameters jobParameters = jobLauncherTestUtils.getUniqueJobParameters();
      // when
      JobExecution jobExecution = jobLauncherTestUtils.launchStep("myStep", jobParameters);
      // then
      Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
   }
}

nb: SpringBatchTest已在v4.1中添加。

编辑以获取其他注释:当应用程序上下文包含多个作业bean时,不可能知道在JobLauncherTestUtils中注入哪一个。在这种情况下,应手动创建JobLauncherTestUtils并使用正在测试的作业配置。这是一个示例:

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersIncrementer;
import org.springframework.batch.core.JobParametersValidator;
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing;
import org.springframework.batch.core.job.DefaultJobParametersValidator;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.test.JobLauncherTestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/*
 * This test class shows how to use the JobLauncherTestUtils when the application
 * context contains multiple jobs. Since the job is autowired in JobLauncherTestUtils (see setter),
 * it is not possible to autowire one job (ambiguous injection). Hence, it is required to either:
 *  - Not autowire the JobLauncherTestUtils (as shown in this class)
 *  - Or separate job definitions and use a test class for each job (better solution IMO, each job has its own test)
 */
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestMultipleJobsWithJobLauncherTestUtils.JobsConfiguration.class)
public class TestMultipleJobsWithJobLauncherTestUtils {
    // don't autowire the JobLauncherTestUtils in this case otherwise No qualifying bean of type 'org.springframework.batch.core.Job' available: expected single matching bean but found 2: job1,job2
    private JobLauncherTestUtils jobLauncherTestUtils = new JobLauncherTestUtils();
    @Autowired
    private Job job1;
    @Autowired
    private Job job2;
    @Autowired
    private JobLauncher jobLauncher;
    @Autowired
    private JobRepository jobRepository;
    @Before
    public void setUp() {
        jobLauncherTestUtils.setJobLauncher(jobLauncher);
        jobLauncherTestUtils.setJobRepository(jobRepository);
    }
    @Test
    public void testJob1() throws Exception {
        // given
        jobLauncherTestUtils.setJob(job1);
        // when
        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        // then
        Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
    }
    @Test
    public void testJob2() throws Exception {
        // given
        jobLauncherTestUtils.setJob(job2);
        // when
        JobExecution jobExecution = jobLauncherTestUtils.launchJob();
        // then
        Assert.assertEquals(ExitStatus.COMPLETED, jobExecution.getExitStatus());
    }
    @Configuration
    @EnableBatchProcessing
    public static class JobsConfiguration {
        @Bean
        public Job job1() {
            return new SimpleJob("job1");
        }
        @Bean
        public Job job2() {
            return new SimpleJob("job2");
        }
        // Don't declare the JobLauncherTestUtils as a bean to avoid dependecy injection
//      @Bean
//      public JobLauncherTestUtils jobLauncherTestUtils() {
//          return new JobLauncherTestUtils();
//      }
    }
    static class SimpleJob implements Job {
        private String name;
        public SimpleJob(String name) {
            this.name = name;
        }
        @Override
        public String getName() {
            return name;
        }
        @Override
        public boolean isRestartable() {
            return false;
        }
        @Override
        public void execute(JobExecution execution) {
            System.out.println("Executing job " + this.name);
            execution.setExitStatus(ExitStatus.COMPLETED);
        }
        @Nullable
        @Override
        public JobParametersIncrementer getJobParametersIncrementer() {
            return null;
        }
        @Override
        public JobParametersValidator getJobParametersValidator() {
            return new DefaultJobParametersValidator();
        }
    }
}

希望这会有所帮助。

最新更新