How to exclude *AutoConfiguration classes in Spring Boot JUnit tests?

前端 未结 13 1010
名媛妹妹
名媛妹妹 2020-12-01 01:51

I tried:

@RunWith(SpringJUnit4ClassRunner.class)
@EnableAutoConfiguration(exclude=CrshAutoConfiguration.class)
@SpringApplicationConfiguration(classes = Appl         


        
相关标签:
13条回答
  • 2020-12-01 02:23
    @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

    0 讨论(0)
  • 2020-12-01 02:24

    I had a similar use case where I wanted to test a Spring Boot configured repository in isolation (in my case without Spring Security autoconfiguration which was failing my test). @SpringApplicationConfiguration uses SpringApplicationContextLoader and that has a JavaDoc stating

    Can be used to test non-web features (like a repository layer) or start an fully-configured embedded servlet container.

    However, like yourself, I could not work out how you are meant to configure the test to only test the repository layer using the main configuration entry point i.e. using your approach of @SpringApplicationConfiguration(classes = Application.class).

    My solution was to create a completely new application context exclusive for testing. So in src/test/java I have two files in a sub-package called repo

    1. RepoIntegrationTest.java
    2. TestRepoConfig.java

    where RepoIntegrationTest.java has

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = TestRepoConfig.class)
    public class RepoIntegrationTest {
    

    and TestRepoConfig.java has

    @SpringBootApplication(exclude = SecurityAutoConfiguration.class)
    public class TestRepoConfig {
    

    It got me out of trouble but it would be really useful if anyone from the Spring Boot team could provide an alternative recommended solution

    0 讨论(0)
  • 2020-12-01 02:26

    If the issue is that your SpringBootApplication/Configuration you are bringing in is component scanning the package your test configurations are in, you can actually remove the @Configuration annotation from the test configurations and you can still use them in the @SpringBootTest annotations. For example, if you have a class Application that is your main configuration and a class TestConfiguration that is a configuration for certain, but not all tests, you can set up your classes as follows:

    @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
    }
    

    And then you can configure your tests in one of two ways:

    1. With the regular 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
      }
      
    2. With the test custom test configuration:

      @SpringBootTest(classes = {TestConfiguration.class}) //this still works!
      //Other annotations here
      public class TestThatUsesCustomTestConfiguration {
          //my test code
      }
      
    0 讨论(0)
  • 2020-12-01 02:28

    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.

    0 讨论(0)
  • 2020-12-01 02:32

    I think that using the @EnableAutoConfiguration annotation on a test class won't work if you are using @SpringApplicationConfiguration to load your Application class. The thing is that you already have a @EnableAutoConfiguration annotation in the Application class that does not exclude the CrshAutoConfiguration.Spring uses that annotation instead of the one on your test class to do the auto configuration of your beans.

    I think that your best bet is to use a different application context for your tests and exclude the CrshAutoConfiguration in that class.

    I did some tests and it seems that @EnableAutoConfiguration on the test class is completely ignore if you are using the @SpringApplicationConfiguration annotation and the SpringJUnit4ClassRunner.

    0 讨论(0)
  • 2020-12-01 02:35

    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
    }
    
    0 讨论(0)
提交回复
热议问题