Как исключить * классы автоконфигурации в тестах Spring Boot JUnit?
Я старался:
@RunWith(SpringJUnit4ClassRunner.class)
@EnableAutoConfiguration(exclude=CrshAutoConfiguration.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class LikeControllerTest {
Однако CRaSSHD все еще запускается. Хотя в настоящее время это не вредит тесту, я бы хотел отключить ненужные модули во время модульного тестирования, чтобы ускорить и избежать возможных конфликтов.
14 ответов
У меня был похожий случай использования, когда я хотел протестировать репозиторий, сконфигурированный Spring Boot, изолированно (в моем случае без автоконфигурации Spring Security, которая не прошла мой тест). @SpringApplicationConfiguration
использования SpringApplicationContextLoader
и это имеет JavaDoc заявляя
Может использоваться для тестирования не веб-функций (например, уровня репозитория) или запуска полностью настроенного встроенного контейнера сервлета.
Однако, как и вы, я не смог понять, как вы собираетесь настроить тест, чтобы тестировать только уровень репозитория, используя основную точку входа в конфигурацию, т.е. используя ваш подход @SpringApplicationConfiguration(classes = Application.class)
,
Мое решение состояло в том, чтобы создать совершенно новый контекст приложения, эксклюзивный для тестирования. Так что в src/test/java у меня есть два файла в подпакете под названием репо
RepoIntegrationTest.java
TestRepoConfig.java
где RepoIntegrationTest.java
имеет
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestRepoConfig.class)
public class RepoIntegrationTest {
а также TestRepoConfig.java
имеет
@SpringBootApplication(exclude = SecurityAutoConfiguration.class)
public class TestRepoConfig {
Это избавило меня от неприятностей, но было бы очень полезно, если бы кто-нибудь из команды Spring Boot мог предложить альтернативное рекомендуемое решение.
Еще один простой способ исключить классы автоконфигурации,
Добавьте ниже подобную конфигурацию к вашему файлу application.yml,
---
spring:
profiles: test
autoconfigure.exclude: org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
Лучшие ответы не указывают на еще более простое и гибкое решение.
просто поместите
@TestPropertySource(properties=
{"spring.autoconfigure.exclude=comma.seperated.ClassNames,com.example.FooAutoConfiguration"})
@SpringBootTest
public class MySpringTest {...}
аннотации над вашим тестовым классом. Это означает, что на другие тесты не влияет особый случай текущего теста. Если есть конфигурация, влияющая на большинство ваших тестов, рассмотрите возможность использования профиля пружины вместо этого, как подсказывает текущий верхний ответ.
Спасибо @skirsch за поддержку в переходе от комментария к ответу.
У меня была похожая проблема, но я нашел другое решение, которое может помочь другим. Я использовал Spring Profiles для разделения классов тестирования и конфигурации приложения.
Создайте класс TestConfig с определенным профилем и исключите любую конфигурацию приложения из сканирования компонентов, которое вы хотите здесь.
В вашем тестовом классе установите профиль, соответствующий TestConfig, и включите его, используя аннотацию @ContextConfiguration.
Например:
конфигурация:
@Profile("test")
@Configuration
@EnableWebMvc
@ComponentScan(
basePackages="your.base.package",
excludeFilters = {
@Filter(type = ASSIGNABLE_TYPE,
value = {
ExcludedAppConfig1.class,
ExcludedAppConfig2.class
})
})
public class TestConfig { ...}
тестовое задание:
@ActiveProfiles("test")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfig.class)
@WebAppConfiguration
public class SomeTest{ ... }
Я думаю, что с помощью @EnableAutoConfiguration
аннотация на тестовом классе не будет работать, если вы используете @SpringApplicationConfiguration
загрузить ваш Application
учебный класс. Дело в том, что у вас уже есть @EnableAutoConfiguration
аннотация в Application
класс, который не исключает CrshAutoConfiguration
,Spring
использует эту аннотацию вместо той, что используется в вашем тестовом классе, для автоматической настройки ваших bean-компонентов.
Я думаю, что вам лучше всего использовать другой контекст приложения для ваших тестов и исключить CrshAutoConfiguration
в этом классе.
Я сделал несколько тестов, и кажется, что @EnableAutoConfiguration
на тестовом классе полностью игнорировать, если вы используете @SpringApplicationConfiguration
аннотация и SpringJUnit4ClassRunner
,
С новым @SpringBootTest
аннотации, я взял этот ответ и изменил его, чтобы использовать профили с @SpringBootApplication
класс конфигурации. @Profile
аннотация необходима для того, чтобы этот класс выбирался только во время определенных интеграционных тестов, которые в этом нуждаются, поскольку другие конфигурации тестов выполняют сканирование различных компонентов.
Вот класс конфигурации:
@Profile("specific-profile")
@SpringBootApplication(scanBasePackages={"com.myco.package1", "com.myco.package2"})
public class SpecificTestConfig {
}
Затем тестовый класс ссылается на этот класс конфигурации:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SpecificTestConfig.class })
@ActiveProfiles({"specific-profile"})
public class MyTest {
}
@SpringBootTest(classes = {Application.class}
, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
, properties="spring.autoconfigure.exclude=com.xx.xx.AutoConfiguration"
)
ссылка: https://github.com/spring-projects/spring-boot/issues/8579
Если проблема заключается в том, что ваша SpringBootApplication/Configuration, которую вы вводите, является компонентом, сканирующим пакет, в котором находятся ваши тестовые конфигурации, вы можете фактически удалить аннотацию @Configuration из тестовых конфигураций и по-прежнему использовать их в аннотациях @SpringBootTest. Например, если у вас есть класс Application, который является вашей основной конфигурацией, и класс TestConfiguration, который является конфигурацией для определенных, но не всех тестов, вы можете настроить свои классы следующим образом:
@Import(Application.class) //or the specific configurations you want
//(Optional) Other Annotations that will not trigger an autowire
public class TestConfiguration {
//your custom test configuration
}
И тогда вы можете настроить свои тесты одним из двух способов:
При штатной конфигурации:
@SpringBootTest(classes = {Application.class}) //won't component scan your configuration because it doesn't have an autowire-able annotation //Other annotations here public class TestThatUsesNormalApplication { //my test code }
С тестовой пользовательской конфигурацией теста:
@SpringBootTest(classes = {TestConfiguration.class}) //this still works! //Other annotations here public class TestThatUsesCustomTestConfiguration { //my test code }
Попал в такую же проблему, не смог исключить основной весенний загрузочный класс во время тестирования. Решил, используя следующий подход.
Вместо использования @SpringBootApplication используйте все три аннотации, которые в нем содержатся, и присвойте имя @Configuration.
@Configuration("myApp")
@EnableAutoConfiguration
@ComponentScan
public class MyApp { .. }
В вашем тестовом классе определите конфигурацию с точно таким же именем:
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
// ugly hack how to exclude main configuration
@Configuration("myApp")
@SpringApplicationConfiguration(classes = MyTest.class)
public class MyTest { ... }
Это должно помочь. Было бы неплохо иметь более эффективный способ отключить автоматическое сканирование для аннотаций конфигурации...
Я боролся с подобной проблемой в течение одного дня... Мой сценарий:
У меня есть приложение SpringBoot, и я использую applicationContext.xml в scr/main/resources
настроить все мои Spring Beans. Для тестирования (интеграционного тестирования) я использую другое applicationContext.xml в test/resources
и все работает как я ожидал: Spring / SpringBoot переопределит applicationContext.xml из scr/main/resources
и будет использовать тот для тестирования, который содержит компоненты, настроенные для тестирования.
Однако, только для одного UnitTest я хотел еще одну настройку для applicationContext.xml, используемого в тестировании, просто для этого теста я хотел использовать некоторые beck-компоненты mockito, чтобы я мог mock
а также verify
и тут началась моя однодневная головная боль!
Проблема в том, что Spring / SpringBoot не переопределяет applicationContext.xml из scr/main/resources
ТОЛЬКО ЕСЛИ файл из test/resources
ИМЕТЕ ЖЕ ИМЯ. Я пытался часами использовать что-то вроде:
@RunWith(SpringJUnit4ClassRunner.class)
@OverrideAutoConfiguration(enabled=true)
@ContextConfiguration({"classpath:applicationContext-test.xml"})
это не сработало, Spring сначала загружал бины из applicationContext.xml в scr/main/resources
Мое решение основано на ответах здесь @myroch и @Stuart:
Определите основную конфигурацию приложения:
@Configuration @ImportResource({"classpath:applicationContext.xml"}) public class MainAppConfig { }
это используется в приложении
@SpringBootApplication
@Import(MainAppConfig.class)
public class SuppressionMain implements CommandLineRunner
Определите TestConfiguration для Test, где вы хотите исключить основную конфигурацию
@ComponentScan( basePackages = "com.mypackage", excludeFilters = { @ComponentScan.Filter(type = ASSIGNABLE_TYPE, value = {MainAppConfig.class}) }) @EnableAutoConfiguration открытый класс TestConfig { }
При этом для этого теста Spring не будет загружать applicationContext.xml и будет загружать только пользовательскую конфигурацию, специфичную для этого теста.
Я думаю, что лучшее решение для SpringBoot 2.0 - это использование профилей.
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
@ActiveProfiles("test")
public class ExcludeAutoConfigIntegrationTest {
// ...
}
spring.autoconfigure.exclude = org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
в любом случае в следующей ссылке, чтобы решить эту проблему, дайте 6 разных вариантов.
Если у вас возникла эта проблема с Spring Boot 1.4.x и выше, вы можете использовать @OverrideAutoConfiguration(enabled=true)
решить проблему.
Подобно тому, что спросили / ответили здесь /questions/20944465/kak-isklyuchit-otklyuchit-opredelennuyu-avtokonfiguratsiyu-v-spring-boot-140-dlya-datajpatest/20944485#20944485
Я также боролся с этим и нашел простой шаблон для выделения контекста теста после краткого чтения документов @ComponentScan.
/ **
* Типобезопасная альтернатива {@link #basePackages} для указания пакетов
* для сканирования аннотированных компонентов. Пакет каждого указанного класса будет проверен.
* Рассмотрите возможность создания специального класса или интерфейса no-op marker в каждом пакете.
* это не служит никакой другой цели, кроме ссылки на этот атрибут.
* /Class<?>[] basePackageClasses() default {};
- Создать пакет для ваших весенних тестов,
("com.example.test")
, - Создайте интерфейс маркера в пакете в качестве спецификатора контекста.
- Предоставьте ссылку на интерфейс маркера в качестве параметра для basePackageClasses.
пример
IsolatedTest.java
package com.example.test;
@RunWith(SpringJUnit4ClassRunner.class)
@ComponentScan(basePackageClasses = {TestDomain.class})
@SpringApplicationConfiguration(classes = IsolatedTest.Config.class)
public class IsolatedTest {
String expected = "Read the documentation on @ComponentScan";
String actual = "Too lazy when I can just search on Stack Overflow.";
@Test
public void testSomething() throws Exception {
assertEquals(expected, actual);
}
@ComponentScan(basePackageClasses = {TestDomain.class})
public static class Config {
public static void main(String[] args) {
SpringApplication.run(Config.class, args);
}
}
}
...
TestDomain.java
package com.example.test;
public interface TestDomain {
//noop marker
}
Таким образом, чтобы отключить автоматическую загрузку всех Bean-компонентов для теста, тестовый класс может явно указать требуемые зависимости. Это можно сделать с помощью
ContextConfiguration
аннотация. например,
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {EmployeeService.class})
public class EmployeeLeavesTest {
@Autowired
private EmployeeService employeeService;
}
В этом, например, только
EmployeeService
класс будет доступен, а другие компоненты не будут загружены.