Подтвердить что ты не робот

Запретить выполнение классов Application/CommandLineRunner во время тестирования JUnit

Если в вашем классе TestCase есть эти аннотации:

@SpringApplicationConfiguration(classes = {Application.class})

это приведет к Application.class, реализующему интерфейс CommandLineRunner, для запуска требуемого метода

public void run(String... args) throws Exception

Я все еще думаю, что это, в основном, нежелательное поведение, поскольку в тестовой среде вы не можете запускать все приложение.

Я имею в виду два решения, чтобы обойти эту проблему:

  • удалить интерфейс CommandLineRunner из моего класса Application
  • иметь другой контекст для тестирования

Оба этих решения требуют большого количества кодирования. У вас есть более удобное решение?

4b9b3361

Ответ 1

Решение Jan может быть достигнуто легче.

В вашем тестовом классе активируйте профиль "test":

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
public class MyFancyTest {}

В вашем CommandLineRunner установите для профиля НЕ тест:

@Component
@Profile("!test")
public class JobCommandLineRunner implements CommandLineRunner {}

Тогда вам не нужно вручную устанавливать профиль в приложении.

Ответ 2

Вы можете определить тестовую конфигурацию в том же пакете, что и ваше приложение, которое выглядит точно таким же, за исключением того, что оно исключает beans реализацию CommandLineRunner. Ключ здесь: @ComponentScan.excludeFilters:

@Configuration
@ComponentScan(excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = CommandLineRunner.class))
@EnableAutoConfiguration
public class TestApplicationConfiguration {
}

Затем просто замените конфигурацию теста:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = TestApplicationConfiguration.class)
public class SomeApplicationTest {
    ...
}

Теперь CommandLineRunner не будет выполнен, потому что они не являются частью конфигурации.

Ответ 3

Как упоминалось в spring документации http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html, вы можете использовать @ContextConfiguration со специальным инициализатором:

ConfigFileApplicationContextInitializer - это ApplicationContextInitializer, который может применяться к вашим тестам для загрузки файлов spring Boot application.properties. Вы можете использовать это, когда вам не нужны полные функции, предоставляемые @SpringApplicationConfiguration.

В этом примере инициализируется anyComponent и вводятся свойства, но методы run (args) не выполняются. ( Application.class - моя главная точка входа spring)

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Application.class, 
                      initializers = ConfigFileApplicationContextInitializer.class)
public class ExtractorTest {
    @Autowired
    AnyComponent anyComponent;

    @Test
    public void testAnyComponent() {
       anyComponent.anyMethod(anyArgument);
    }
}

Ответ 4

Я немного опаздываю на вечеринку, но разумным подходом является отметка bean с помощью @ConditionalOnProperty, например.

@ConditionalOnProperty(prefix = "job.autorun", name = "enabled", havingValue = "true", matchIfMissing = true)
public CommandLineRunner myRunner() {...}

Следующая аннотация затем отключит ее в тестах:

@SpringBootTest(properties = {"job.autorun.enabled=false"})

Ответ 5

Я решаю это, не внедряя CommandLineRunner. Просто получите bean из контекста и вызовите на нем метод, передав argv. Таким образом, вы получите тот же результат, и приложение не запустится автоматически при запуске тестов.

Ответ 6

Предыдущие ответы не помогли мне. Я закончил использование разных профилей - пример для метода init в Spring Boot:

SpringApplication app = new SpringApplication(AppConfig.class);
app.setAdditionalProfiles("production");
app.run(args);

Это не выполняется во время тестов, поэтому мы здесь в безопасности.

Все тесты имеют свой собственный "тест" профиля (который также полезен и многими другими способами):

@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
public class MyFancyTest {}

Бегун командной строки аннотируется профилем "production", поэтому тесты игнорируют его:

@Component
@Profile("production")
public class JobCommandLineRunner implements CommandLineRunner {}