не может загрузить контекст приложения из junit для весеннего пакетного задания - PullRequest
0 голосов
/ 04 марта 2019

У меня проблемы с загрузкой контекста приложения из тестов junit для моих весенних пакетных тестов.Я ссылался на весеннюю документацию https://docs.spring.io/spring-batch/trunk/reference/html/testing.html, а также на любую доступную информацию, которую я мог найти в Интернете, но все еще не мог получить простую работу по тестированию джунтов.

Я использую аннотации для загрузки контекста приложения, код приведен ниже.Моя цель - уметь тестировать отдельные шаги.

Я также клонировал некоторые примеры из Интернета, но при запуске на моем локальном компьютере они выдают ту же ошибку - невозможно загрузить контекст приложения ... это заставило меня задуматься о том, как эти тесты должны выполняться?Run 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());
   }


}

Код взят из весенней документации.

Я новичок в этом деле.Спасибо за вашу помощь.

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();
          }

    }

Надеюсь, это кому-нибудь поможеткак я.

1 Ответ

0 голосов
/ 05 марта 2019

Моя цель - проверить отдельные шаги.

Вы можете использовать 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.

РЕДАКТИРОВАТЬ для дополнительных комментариев: Когда контекст приложения содержит несколько бинов задания, невозможно узнать, какой из них внедрить в 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();
        }

    }
}

Надеюсь, это поможет.

...