it-roy-ru.com

Как исключить * классы автоконфигурации в тестах Spring Boot JUnit?

Я старался:

@RunWith(SpringJUnit4ClassRunner.class)
@EnableAutoConfiguration(exclude=CrshAutoConfiguration.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class LikeControllerTest {

Однако CRaSSHD все еще запускается. Хотя в настоящее время это не вредит тесту, я бы хотел отключить ненужные модули во время модульного тестирования, чтобы ускорить и избежать возможных конфликтов.

50
Hendy Irawan

Лучшие ответы не указывают на еще более простое и гибкое решение.

просто поместите 

@TestPropertySource(properties=
{"spring.autoconfigure.exclude=comma.seperated.ClassNames,com.example.FooAutoConfiguration"})
@SpringBootTest
public class MySpringTest {...}

аннотации над вашим тестовым классом. Это означает, что на другие тесты не влияет особый случай текущего теста. Если есть конфигурация, влияющая на большинство ваших тестов, рассмотрите возможность использования профиля пружины вместо этого, как подсказывает текущий верхний ответ.

Спасибо @skirsch за поддержку, чтобы я перешел от комментария к ответу.

3
coderatchet

Еще один простой способ исключить классы автоконфигурации,

Добавьте ниже похожую конфигурацию к вашему application.yml file,

---
spring:
  profiles: test
  autoconfigure.exclude: org.springframework.boot.autoconfigure.session.SessionAutoConfiguration
47
Kane

У меня был похожий случай, когда я хотел протестировать репозиторий, сконфигурированный Spring Boot, в отдельности (в моем случае без автоконфигурации Spring Security, которая не прошла мой тест). @SpringApplicationConfiguration использует SpringApplicationContextLoader и имеет указание JavaDoc

Может использоваться для тестирования не веб-функций (например, уровня хранилища) или Запустите полностью настроенный встроенный контейнер сервлетов.

Однако, как и вы, я не смог понять, как вы собираетесь настроить тест, чтобы тестировать только уровень репозитория, используя основную точку входа в конфигурацию, т.е. используя ваш подход @SpringApplicationConfiguration(classes = Application.class).

Мое решение состояло в том, чтобы создать совершенно новый контекст приложения, эксклюзивный для тестирования. Так что в src/test/Java у меня есть два файла в подпакете под названием репо

  1. RepoIntegrationTest.Java
  2. 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 мог предложить альтернативное рекомендуемое решение.

27
Matt C

У меня была похожая проблема, но я нашел другое решение, которое может помочь другим. Я использовал Spring Profiles для разделения классов тестирования и конфигурации приложения. 

  1. Создайте класс TestConfig с определенным профилем и исключите любую конфигурацию приложения из сканирования компонентов, которое вы хотите здесь.

  2. В вашем тестовом классе установите профиль, соответствующий 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{ ... }
11
Stuart

Я думаю, что использование аннотации @EnableAutoConfiguration в тестовом классе не сработает, если вы используете @SpringApplicationConfiguration для загрузки своего класса Application. Дело в том, что у вас уже есть аннотация @EnableAutoConfiguration в классе Application, которая не исключает CrshAutoConfiguration.Spring, которая использует эту аннотацию вместо той, что используется в вашем тестовом классе, для автоматической настройки ваших bean-компонентов. 

Я думаю, что вам лучше всего использовать другой контекст приложения для ваших тестов и исключить CrshAutoConfiguration в этом классе.

Я провел несколько тестов, и кажется, что @EnableAutoConfiguration в тестовом классе полностью игнорируется, если вы используете аннотацию @SpringApplicationConfiguration и SpringJUnit4ClassRunner.

6
Jean-Philippe Bond

С новой аннотацией @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 {

}
6
James McShane
@SpringBootTest(classes = {Application.class}
              , webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT
              , properties="spring.autoconfigure.exclude=com.xx.xx.AutoConfiguration"
               )

ref: https://github.com/spring-projects/spring-boot/issues/8579

4
Kingson wu

попал в такую ​​же проблему, не смог исключить основной весенний загрузочный класс во время тестирования. Решил, используя следующий подход.

Вместо использования @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 { ... }

Это должно помочь. Было бы хорошо иметь какой-то лучший способ отключить автоматическое сканирование для комментариев к конфигурации ...

2
myroch

Я думаю, что лучшее решение для 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 различных вариантов решения этой проблемы.

1
oriaj

Если проблема заключается в том, что ваша 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
}

И тогда вы можете настроить свои тесты одним из двух способов:

  1. При штатной конфигурации:

    @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
    }
    
  2. С тестовой пользовательской конфигурацией теста:

    @SpringBootTest(classes = {TestConfiguration.class}) //this still works!
    //Other annotations here
    public class TestThatUsesCustomTestConfiguration {
        //my test code
    }
    
1
Taugenichts

Если у вас возникла эта проблема с Spring Boot 1.4.x и выше, вы можете использовать @OverrideAutoConfiguration(enabled=true) для решения проблемы.

Подобно тому, что спросили/ответили здесь https://stackoverflow.com/a/39253304/1410035

0
Tom Saleeba

Я также боролся с этим и нашел простой шаблон для изоляции тестового контекста после краткого чтения @ComponentScan docs.

/ **
* Типобезопасная альтернатива {@link #basePackages} для указания пакетов
* для сканирования аннотированных компонентов. Пакет каждого указанного класса будет проверен.
* Рассмотрите возможность создания специального класса или интерфейса no-op mark в каждом пакете
* это не имеет никакого значения, кроме ссылки на этот атрибут.
* /
Class<?>[] basePackageClasses() default {};

  1. Создайте пакет для ваших весенних тестов, ("com.example.test").
  2. Создайте интерфейс маркера в пакете в качестве спецификатора контекста.
  3. Предоставить ссылку на интерфейс маркера в качестве параметра для 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
}
0
Eddie B

Я боролся с подобной проблемой в течение одного дня ... Мой сценарий:

У меня есть приложение SpringBoot, и я использую applicationContext.xml в scr/main/resources для настройки всех своих Spring Beans. Для тестирования (интеграционного тестирования) я использую другой applicationContext.xml в test/resources, и все работает так, как я ожидал: Spring/SpringBoot переопределит applicationContext.xml из scr/main/resources и будет использовать тот для тестирования который содержал бины, настроенные для тестирования.

Тем не менее, только для одного UnitTest я хотел еще одну настройку для applicationContext.xml , используемого в тестировании, просто для этого теста я хотел использовать некоторые beck-компоненты, поэтому я мог использовать mock и verify, и здесь началась моя однодневная работа. -ache!

Проблема заключается в том, что 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:

  1. Определите основную конфигурацию приложения:

    @Configuration @ImportResource({"classpath:applicationContext.xml"}) public class MainAppConfig { }

это используется в приложении

@SpringBootApplication
@Import(MainAppConfig.class)
public class SuppressionMain implements CommandLineRunner
  1. Определите TestConfiguration для Test, где вы хотите исключить основную конфигурацию

    @ComponentScan ( BasePackages = "com.mypackage", ExcludeFilters = { @ ComponentScan.Filter (type = ASSIGNABLE_TYPE, Value = {MainAppConfig.class}) }) @ EnableAutoConfiguration Открытый класс TestConfig {}

Таким образом, для этого теста Spring не будет загружать applicationContext.xml и будет загружать только пользовательскую конфигурацию, специфичную для этого теста.

0
razvang