如何在Spring Boot JUnit测试中排除* AutoConfiguration类?

时间:2014-11-02 09:59:01

标签: java spring junit spring-boot

我试过了:

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

然而,CRaSSHD仍然启动。虽然目前它不会对测试造成损害,但我希望在单元测试期间禁用不必要的模块以加快速度并避免潜在的冲突。

14 个答案:

答案 0 :(得分:47)

排除自动配置类的另一种简单方法,

application.yml 文件

中添加以下类似的配置
---
spring:
  profiles: test
  autoconfigure.exclude: org.springframework.boot.autoconfigure.session.SessionAutoConfiguration

答案 1 :(得分:28)

我有一个类似的用例,我希望单独测试一个Spring Boot配置的存储库(在我的情况下没有Spring Security自动配置,但我的测试失败了)。 @SpringApplicationConfiguration使用SpringApplicationContextLoader并且有一个JavaDoc说明

  

可用于测试非Web功能(如存储库层)或   启动一个完全配置的嵌入式servlet容器。

然而,就像你自己一样,我无法弄清楚你是如何配置测试的,只是使用主配置入口点测试存储库层,即使用@SpringApplicationConfiguration(classes = Application.class)的方法。

我的解决方案是创建一个专门用于测试的全新应用程序上下文。所以在src / test / java中,我在一个名为repo的子包中有两个文件

  1. RepoIntegrationTest.java
  2. TestRepoConfig.java
  3. 其中RepoIntegrationTest.java

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

    TestRepoConfig.java

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

    它让我摆脱了麻烦,但如果来自Spring Boot团队的任何人都可以提供替代的推荐解决方案,那将非常有用

答案 2 :(得分:11)

我遇到了类似的问题,但我找到了一个可以帮助他人的不同解决方案。我使用Spring Profiles来分离测试和应用程序配置类。

  1. 使用特定的配置文件创建一个TestConfig类,并从您希望的组件扫描中排除任何应用程序配置。

  2. 在测试类中,将配置文件设置为与TestConfig匹配,并使用@ContextConfiguration批注包含它。

  3. 例如:

    配置:

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

答案 3 :(得分:11)

最重要的答案并不指向更简单,更灵活的解决方案。

只需放置一个

@TestPropertySource(properties=
{"spring.autoconfigure.exclude=comma.seperated.ClassNames,com.example.FooAutoConfiguration"})
@SpringBootTest
public class MySpringTest {...}
测试课程上方的

注释。这意味着其他测试不受当前测试的特殊情况的影响。如果某个配置会影响您的大多数测试,请考虑使用spring配置文件代替当前最常见的答案。

  

感谢@skirsch鼓励我将其从评论升级为答案。

答案 4 :(得分:7)

如果您使用@EnableAutoConfiguration加载@SpringApplicationConfiguration课程,我认为在测试课程中使用Application注释不会奏效。问题是,@EnableAutoConfiguration类中已有Application注释,但不排除CrshAutoConfigurationSpring使用该注释而不是测试类中的注释执行bean的自动配置。

我认为您最好的选择是为测试使用不同的应用程序上下文,并排除该类中的CrshAutoConfiguration

我做了一些测试,如果您使用@EnableAutoConfiguration注释和@SpringApplicationConfiguration,似乎完全忽略了测试类上的SpringJUnit4ClassRunner

答案 5 :(得分:6)

使用新的@SpringBootTest注释,我使用了this answer并对其进行了修改,以使用具有@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 :(得分:4)

@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

答案 7 :(得分:2)

遇到了同样的问题,在测试过程中无法排除主弹簧引导类。使用以下方法解决了它。

不使用@SpringBootApplication,而是使用它包含的所有三个注释,并将名称分配给@Configuration

$lastname

在您的测试类中定义具有完全相同名称的配置:

@Configuration("myApp")
@EnableAutoConfiguration
@ComponentScan
public class MyApp { .. }

这应该有所帮助。很高兴有一些更好的方法来禁用自动扫描配置注释......

答案 8 :(得分:2)

如果问题是引入的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
    }
    

答案 9 :(得分:1)

有一天,我一直在为类似的问题而苦苦挣扎...我的情况:

我有一个SpringBoot应用程序,我在scr/main/resources中使用 applicationContext.xml 来配置我所有的Spring Bean。 为了进行测试(集成测试),我在test/resources中使用了另一个 applicationContext.xml ,并且一切正常,如我所料:Spring / SpringBoot将从{覆盖 applicationContext.xml {1}},并且将使用包含用于测试的bean的“ Testing”。

但是,对于一个单元测试,我想要为测试中使用的 applicationContext.xml 进行另一种自定义,对于这个测试,我想要使用一些模仿bean,因此我可以scr/main/resourcesmock,这开始了我一天的头痛!

问题是,只有来自verify的文件具有相同的名称时,Spring / SpringBoot才会覆盖scr/main/resources applicationContext.xml 。 我试了几个小时使用类似的东西:

test/resources

它不起作用,Spring首先从@RunWith(SpringJUnit4ClassRunner.class) @OverrideAutoConfiguration(enabled=true) @ContextConfiguration({"classpath:applicationContext-test.xml"})

中的 applicationContext.xml 中加载bean。

我的解决方案基于@myroch和@Stuart的回答:

  1. 定义应用程序的主要配置:

    scr/main/resources

在应用程序中使用

@Configuration
@ImportResource({"classpath:applicationContext.xml"})
public class MainAppConfig {
}
  1. 在要排除主要配置的测试中定义TestConfiguration

    @ComponentScan( basePackages =“ com.mypackage”,         excludeFilters = {                 @ ComponentScan.Filter(type = ASSIGNABLE_TYPE,                         值= {MainAppConfig.class})         }) @EnableAutoConfiguration 公共类TestConfig { }

这样做,对于此测试,Spring将不会加载 applicationContext.xml ,而只会加载特定于该测试的自定义配置。

答案 10 :(得分:1)

我认为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

无论如何,下面的link提供了6种不同的解决方案。

答案 11 :(得分:0)

我也在努力解决这个问题,并在粗略阅读@ComponentScan文档之后找到了一个简单的模式来隔离测试上下文。

  

/ **
       *用于指定包裹的{@link #basePackages}的类型安全替代品        *扫描带注释的组件。将扫描指定的每个类的包        * 考虑在每个包中创建一个特殊的无操作标记类或接口
       * 除了被此属性引用之外没有任何其他用途。
       * /
      Class<?>[] basePackageClasses() default {};

  1. 为您的春季测试("com.example.test")创建一个包。
  2. 在包中创建标记接口作为上下文限定符。
  3. 将标记接口引用作为参数提供给basePackageClasses。
  4. 示例

    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
    }
    

答案 12 :(得分:0)

如果您在Spring Boot 1.4.x及更高版本中遇到此问题,则可以使用@OverrideAutoConfiguration(enabled=true)来解决问题。

与此处https://stackoverflow.com/a/39253304/1410035

的提问/回答类似

答案 13 :(得分:0)

因此要禁用测试的所有 Bean 的自动加载,测试类可以明确提及所需的依赖项。 这可以使用 ContextConfiguration 注释来完成。 例如,

@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {EmployeeService.class})
public class EmployeeLeavesTest { 

   @Autowired
   private EmployeeService employeeService;

}

在这个例子中,只有 EmployeeService 类可用,其他 bean 不会被加载。