我在春季批处理测试中加载应用程序上下文时遇到了困难。我推荐了春季文档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)
来启动特定步骤,而不是整个工作。如果要单元测试特定步骤,我建议仅导入测试步骤所需的配置(我指的是RestTemplateConfig
,SftpConfig
等,除非该步骤确实需要这些)。
请注意,在测试上下文中应将正在测试的作业声明为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();
}
}
}
希望这会有所帮助。