Запретить выполнение классов Application/CommandLineRunner во время тестирования JUnit
Если в вашем классе TestCase есть эти аннотации:
@SpringApplicationConfiguration(classes = {Application.class})
это приведет к Application.class
, реализующему интерфейс CommandLineRunner
, для запуска требуемого метода
public void run(String... args) throws Exception
Я все еще думаю, что это, в основном, нежелательное поведение, поскольку в тестовой среде вы не можете запускать все приложение.
Я имею в виду два решения, чтобы обойти эту проблему:
- удалить интерфейс
CommandLineRunner
из моего класса Application
- иметь другой контекст для тестирования
Оба этих решения требуют большого количества кодирования.
У вас есть более удобное решение?
Ответы
Ответ 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 {}