【问题标题】:Override a single @Configuration class on every spring boot @Test在每个春季启动 @Test 上覆盖单个 @Configuration 类
【发布时间】:2016-12-26 18:17:52
【问题描述】:

在我的 Spring Boot 应用程序中,我只想在我的所有测试中使用测试配置覆盖我的 @Configuration 类之一(特别是我的 @EnableAuthorizationServer @Configuration 类)。

到目前为止,在对spring boot testing featuresspring integration testing features 进行了概述之后,还没有直接的解决方案浮出水面:

  • @TestConfiguration: 是用来扩展的,不是覆盖的;
  • @ContextConfiguration(classes=…​)@SpringApplicationConfiguration(classes =…​) 让我覆盖整个配置,而不仅仅是一个类;
  • 建议在@Test 中使用内部@Configuration 类覆盖默认配置,但未提供示例;

有什么建议吗?

【问题讨论】:

    标签: spring spring-boot spring-test


    【解决方案1】:

    内部测试配置

    您的测试的内部@Configuration 示例:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class SomeTest {
    
        @Configuration
        static class ContextConfiguration {
            @Bean
            @Primary //may omit this if this is the only SomeBean defined/visible
            public SomeBean someBean () {
                return new SomeBean();
            }
        }
    
        @Autowired
        private SomeBean someBean;
    
        @Test
        public void testMethod() {
            // test
        }
    }
    

    可重用的测试配置

    如果您希望为多个测试重用测试配置,您可以使用 Spring Profile @Profile("test") 定义一个独立的配置类。然后,让您的测试类使用@ActiveProfiles("test") 激活配置文件。查看完整代码:

    @RunWith(SpringRunner.class)
    @SpringBootTests
    @ActiveProfiles("test")
    public class SomeTest {
    
        @Autowired
        private SomeBean someBean;
    
        @Test
        public void testMethod() {
            // test
        }
    }
    
    @Configuration
    @Profile("test")
    public class TestConfiguration {
        @Bean
        @Primary //may omit this if this is the only SomeBean defined/visible
        public SomeBean someBean() {
            return new SomeBean();
        }
    }
    

    @Primary

    bean定义上的@Primary注解是为了保证如果找到多个的话,这个优先。

    【讨论】:

    • 谢谢。我注意到我还可以通过简单地将覆盖@EnableAuthorizationServer @Configuration 类放在src/test/java 上来覆盖所有测试中的类。春季启动规则:-)
    • 作为旁注,如果您只需要更改特定 @Configuration 上的一个值,而不是覆盖它,您可以为您的测试启用特定的 Spring Boot 配置文件(例如名为 test)在您的测试类上使用注释@ActiveProfiles({"test", ...})。然后你的@Configuration 上的一个简单的if (Arrays.asList(environment.getActiveProfiles()).contains("test")) 就可以了。
    • 如果其他 bean 之一在内部使用,您的解决方案将失败,它是由 SomeBean 类注入的。为了使它工作,只需在 SpringBootTest 注解使用的类列表中添加 ContextConfiguration 类。即:@SpringBootTest(classes = {Application.class, SomeTest.ContextConfiguration.class})
    • “可重用”部分不起作用。在我的示例中,尽管将 @Primary 放在 test-config 中的 bean 上,但 Spring 用 main-config 中的 bean 覆盖它。 IE。它确实是压倒一切的,只是不是你期望的那样——选择了错误的 bean。
    • @Marksim 是的,我遇到了同样的问题。如果您像作者提到的那样使用@TestConfiguration.(而不是@Configuration),那么Beans 会被正确拾取。而且我更喜欢@Imort 而不是@SpringBootTest(classes=...),不知何故,在某些情况下我得到了有线行为,其中一个额外的@Import 的测试有效而另一个没有。用于测试的这个洞 Spring 配置需要大量时间才能理解。噗
    【解决方案2】:

    你应该使用spring boot profiles:

    1. 使用 @Profile("test") 注释您的测试配置。
    2. 使用 @Profile("production") 注释您的生产配置。
    3. 在您的属性文件中设置生产配置文件:spring.profiles.active=production
    4. 使用@Profile("test") 在您的测试类中设置测试配置文件。

    因此,当您的应用程序启动时,它将使用“生产”类,而当测试启动时,它将使用“测试”类。

    如果您使用内部/嵌套 @Configuration 类,它将被用来代替您的应用程序的主要配置。

    【讨论】:

      【解决方案3】:

      我最近不得不创建我们的应用程序的开发版本,它应该在没有任何命令行参数的情况下使用开箱即用的dev 活动配置文件运行。我通过将这一类添加为新条目来解决它,它以编程方式设置活动配置文件:

      package ...;
      
      import org.springframework.boot.SpringApplication;
      import org.springframework.context.annotation.Import;
      import org.springframework.core.env.ConfigurableEnvironment;
      import org.springframework.core.env.StandardEnvironment;
      
      @Import(OriginalApplication.class)
      public class DevelopmentApplication {
          public static void main(String[] args) {
              SpringApplication application =
                  new SpringApplication(DevelopmentApplication.class);
              ConfigurableEnvironment environment = new StandardEnvironment();
              environment.setActiveProfiles("dev");
              application.setEnvironment(environment);
              application.run(args);
          }
      }
      

      更多详情请见Spring Boot Profiles Example by Arvind Rai

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-17
        • 2014-10-06
        • 1970-01-01
        • 2018-08-02
        • 2023-03-17
        • 2017-09-11
        • 2015-04-18
        • 2017-06-24
        相关资源
        最近更新 更多