programing

Spring Boot JUnit 테스트에서 * AutoConfiguration 클래스를 제외하는 방법은 무엇입니까?

nasanasas 2020. 12. 11. 08:18
반응형

Spring Boot JUnit 테스트에서 * AutoConfiguration 클래스를 제외하는 방법은 무엇입니까?


나는 시도했다 :

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

그러나 CRaSSHD는 여전히 시작됩니다. 현재 테스트에 해를 끼치지는 않지만 단위 테스트 중에 불필요한 모듈을 비활성화하여 속도를 높이고 잠재적 충돌을 피하고 싶습니다.


상위 답변은 더 간단하고 유연한 솔루션을 가리 키지 않습니다.

그냥 배치

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

테스트 클래스 위의 주석. 즉, 다른 테스트는 현재 테스트의 특별한 경우에 영향을받지 않습니다. 대부분의 테스트에 영향을 미치는 구성이있는 경우 현재 최고 답변이 제안하는대로 대신 스프링 프로필을 사용하는 것이 좋습니다.

댓글에서 답변으로 업그레이드하도록 격려해 주신 @skirsch에게 감사드립니다.


자동 구성 클래스를 제외하는 또 다른 간단한 방법은

application.yml 파일에 유사한 구성을 아래에 추가 하십시오.

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

Spring Boot 구성 저장소를 격리하여 테스트하려는 유사한 사용 사례가있었습니다 (내 경우에는 테스트에 실패한 Spring Security 자동 구성이 없음). @SpringApplicationConfiguration사용 SpringApplicationContextLoader하고 JavaDoc이

웹이 아닌 기능 (예 : 저장소 레이어)을 테스트하거나 완전히 구성된 임베디드 서블릿 컨테이너를 시작하는 데 사용할 수 있습니다.

그러나 자신과 마찬가지로 기본 구성 진입 점을 사용하여 저장소 계층 만 테스트하도록 테스트를 구성하는 방법, 즉 @SpringApplicationConfiguration(classes = Application.class).

내 솔루션은 테스트 전용으로 완전히 새로운 애플리케이션 컨텍스트를 만드는 것이 었습니다. 따라서 src / test / java에는 repo라는 하위 패키지에 두 개의 파일이 있습니다.

  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 팀의 누군가가 대체 권장 솔루션을 제공 할 수 있다면 정말 유용 할 것입니다.


비슷한 문제가 있었지만 다른 사람에게 도움이 될 수있는 다른 해결책을 찾았습니다. 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{ ... }

@EnableAutoConfiguration클래스 @SpringApplicationConfiguration를로드 하는 사용 하는 경우 테스트 클래스 에서 주석 을 사용하는 것이 작동하지 않을 것이라고 생각합니다 Application. 문제는 클래스 @EnableAutoConfiguration이미 . 테스트 클래스의 주석 대신 해당 주석을 사용하여 Bean의 자동 구성을 수행합니다.ApplicationCrshAutoConfigurationSpring

가장 좋은 방법은 테스트에 다른 응용 프로그램 컨텍스트를 사용하고 CrshAutoConfiguration해당 클래스에서 제외하는 것 입니다.

몇 가지 테스트를 수행 @EnableAutoConfiguration했으며 @SpringApplicationConfiguration주석과 .NET Framework를 사용하는 경우 테스트 클래스에서 완전히 무시되는 것 같습니다 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("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 { ... }

이것이 도움이 될 것입니다. 구성 주석에 대한 자동 검색을 비활성화하는 더 좋은 방법을 마련하면 좋을 것입니다.


문제가 가져온 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
    }
    

비슷한 문제로 하루 동안 고생했습니다 ... 내 시나리오 :

I have a SpringBoot application and I use applicationContext.xml in scr/main/resources to configure all my Spring Beans. For testing(integration testing) I use another applicationContext.xml in test/resources and things worked as I have expected: Spring/SpringBoot would override applicationContext.xml from scr/main/resources and would use the one for Testing which contained the beans configured for testing.

However, just for one UnitTest I wanted yet another customization for the applicationContext.xml used in Testing, just for this Test I wanted to used some mockito beans, so I could mock and verify, and here started my one day head-ache!

The problem is that Spring/SpringBoot doesn't not override the applicationContext.xml from scr/main/resources ONLY IF the file from test/resources HAS the SAME NAME. I tried for hours to use something like:

@RunWith(SpringJUnit4ClassRunner.class)
@OverrideAutoConfiguration(enabled=true)
@ContextConfiguration({"classpath:applicationContext-test.xml"})

it did not work, Spring was first loading the beans from applicationContext.xml in scr/main/resources

My solution based on the answers here by @myroch and @Stuart:

  1. Define the main configuration of the application:

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

this is used in the application

@SpringBootApplication
@Import(MainAppConfig.class)
public class SuppressionMain implements CommandLineRunner
  1. Define a TestConfiguration for the Test where you want to exclude the main configuration

    @ComponentScan( basePackages = "com.mypackage", excludeFilters = { @ComponentScan.Filter(type = ASSIGNABLE_TYPE, value = {MainAppConfig.class}) }) @EnableAutoConfiguration public class TestConfig { }

By doing this, for this Test, Spring will not load applicationContext.xml and will load only the custom configuration specific for this Test.


I struggled with this as well and found a simple pattern to isolate the test context after a cursory read of the @ComponentScan docs.

/**
* Type-safe alternative to {@link #basePackages} for specifying the packages
* to scan for annotated components. The package of each class specified will be scanned.
* Consider creating a special no-op marker class or interface in each package
* that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};

  1. Create a package for your spring tests, ("com.example.test").
  2. Create a marker interface in the package as a context qualifier.
  3. Provide the marker interface reference as a parameter to basePackageClasses.

Example


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
}

If you're having this problem with Spring Boot 1.4.x and up, you might be able to use @OverrideAutoConfiguration(enabled=true) to solve the problem.

Similar to what was asked/answered here https://stackoverflow.com/a/39253304/1410035


I think that the best solution currently for springBoot 2.0 is using profiles

@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

anyway in the following link give 6 different alternatives to solve this.

참고URL : https://stackoverflow.com/questions/26698071/how-to-exclude-autoconfiguration-classes-in-spring-boot-junit-tests

반응형