无法从 junit 为 spring 批处理作业加载应用程序上下文
cannot load application context from junit for spring batch job
我在为 spring 批测试从 junit 测试加载应用程序上下文时遇到问题。我参考了 spring 文档 https://docs.spring.io/spring-batch/trunk/reference/html/testing.html 以及我可以在网上找到的所有可用信息,但仍然无法获得简单的 junit 测试工作。
我正在使用注释来加载应用上下文,代码如下。我的目标是能够测试各个步骤。
我还从网络上克隆了一些示例,但是当 运行 在我的本地计算机上时,它们会给我同样的错误 - 无法加载应用程序上下文...这让我开始思考这些测试应该如何进行运行? 运行 As -> junit tests 是如何对所有单元进行测试的运行...不是吗?
@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());
}
}
代码来自 spring 文档。
我是新手。感谢您的帮助。
堆栈跟踪:
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();
}
}
希望这对像我这样的人有所帮助。
My aim is to be able to test individual steps.
您可以使用 JobLauncherTestUtils#launchStep(String stepName)
启动特定步骤而不是整个作业。如果您想对特定步骤进行单元测试,我建议仅导入测试该步骤所需的配置(我指的是 RestTemplateConfig
、SftpConfig
等,除非该步骤确实需要这些配置)。
请注意,被测作业应在测试上下文中声明为 bean,因为它 is autowired 在 JobLauncherTestUtils
中。在您的情况下,我假设它是在 BatchProcessingConfiguration
class.
中定义的
典型的步骤测试类似于:
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());
}
}
注意:SpringBatchTest
在 v4.1 中已 added。
编辑以获取更多评论: 当应用程序上下文包含多个作业 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();
}
}
}
希望这对您有所帮助。
我在为 spring 批测试从 junit 测试加载应用程序上下文时遇到问题。我参考了 spring 文档 https://docs.spring.io/spring-batch/trunk/reference/html/testing.html 以及我可以在网上找到的所有可用信息,但仍然无法获得简单的 junit 测试工作。
我正在使用注释来加载应用上下文,代码如下。我的目标是能够测试各个步骤。
我还从网络上克隆了一些示例,但是当 运行 在我的本地计算机上时,它们会给我同样的错误 - 无法加载应用程序上下文...这让我开始思考这些测试应该如何进行运行? 运行 As -> junit tests 是如何对所有单元进行测试的运行...不是吗?
@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());
}
}
代码来自 spring 文档。
我是新手。感谢您的帮助。
堆栈跟踪:
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();
}
}
希望这对像我这样的人有所帮助。
My aim is to be able to test individual steps.
您可以使用 JobLauncherTestUtils#launchStep(String stepName)
启动特定步骤而不是整个作业。如果您想对特定步骤进行单元测试,我建议仅导入测试该步骤所需的配置(我指的是 RestTemplateConfig
、SftpConfig
等,除非该步骤确实需要这些配置)。
请注意,被测作业应在测试上下文中声明为 bean,因为它 is autowired 在 JobLauncherTestUtils
中。在您的情况下,我假设它是在 BatchProcessingConfiguration
class.
典型的步骤测试类似于:
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());
}
}
注意:SpringBatchTest
在 v4.1 中已 added。
编辑以获取更多评论: 当应用程序上下文包含多个作业 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();
}
}
}
希望这对您有所帮助。