Java 如何使用@ConfigurationProperties和@Autowired测试类

Java 如何使用@ConfigurationProperties和@Autowired测试类,java,properties,spring-boot,Java,Properties,Spring Boot,我想测试应用程序的小部分,它们依赖于加载了@Autowired和@ConfigurationProperties的属性。我正在寻找一种只加载所需属性而不总是加载整个ApplicationContext的解决方案。 以下为简化示例: @TestPropertySource(locations = "/SettingsTest.properties") @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {T

我想测试应用程序的小部分,它们依赖于加载了
@Autowired
@ConfigurationProperties
的属性。我正在寻找一种只加载所需属性而不总是加载整个
ApplicationContext
的解决方案。 以下为简化示例:

@TestPropertySource(locations = "/SettingsTest.properties")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestSettings.class, TestConfiguration.class})
public class SettingsTest {
    @Autowired
    TestConfiguration config;

    @Test
    public void testConfig(){
        Assert.assertEquals("TEST_PROPERTY", config.settings().getProperty());
    }
}
配置类:

public class TestConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "test")
    public TestSettings settings (){
        return new TestSettings();
    }
}
设置类:

public class TestSettings {
    private String property;

    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}
资源文件夹中的属性文件包含以下条目:

test.property=TEST_PROPERTY
在我当前的设置中,配置不为null,但没有可用的字段。 字段不是字段的原因应该与我使用的不是Springboot而是Spring这一事实有关。 那么,Springboot的运行方式是什么呢

编辑: 我想这样做的原因是:我有一个解析文本文件的解析器,使用的正则表达式存储在属性文件中。 为了测试这一点,我只想加载这个解析器所需的属性,这些属性在TestSettings上面的示例中

在阅读评论时,我已经注意到这不再是单元测试了。然而,在这个小测试中使用完整的Spring引导配置对我来说似乎有点太多了。这就是为什么我问是否有可能只加载一个具有属性的类。

几点:

  • 在主包中不需要“TestConfiguration”类,因为它所做的只是配置“TestSettings”bean。您只需注释TestSettings类本身就可以做到这一点

  • 通常,您会使用@SpringApplicationConfiguration注释加载测试所需的上下文,并传递应用程序类的名称。但是,您说过不想加载整个ApplicationContext(尽管不清楚为什么),所以您需要创建一个特殊的配置类来仅为测试加载。下面我将其称为“TestConfigurationNew”,以避免与您最初使用的TestConfiguration类混淆

  • 在Spring引导世界中,所有属性通常保存在“application.properties”文件中;但也有可能将它们储存在其他地方。下面,我指定了您建议的“SettingsTest.properties”文件。请注意,您可以拥有此文件的两个副本,一个在main/resources文件夹中,另一个在test/resources文件夹中进行测试

  • 更改代码如下:

    @EnableConfigurationProperties
    public class TestConfiguration {
    
        @Bean
        @ConfigurationProperties(prefix = "test")
        public TestSettings settings (){
            return new TestSettings();
        }
    }
    
    TestSettings.java(在主包中)

    SettingsTest.java(在测试包中)

    TestConfigurationNew.java(在测试包中):


    现在,这应该按照您想要的方式工作。

    您需要使用
    @EnableConfigurationProperties
    对TestConfiguration进行注释,如下所示:

    @EnableConfigurationProperties
    public class TestConfiguration {
    
        @Bean
        @ConfigurationProperties(prefix = "test")
        public TestSettings settings (){
            return new TestSettings();
        }
    }
    
    另外,您只需在
    @ContextConfiguration
    中包含
    TestConfiguration.class
    ,您的
    设置测试
    类:

    @TestPropertySource(locations = "/SettingsTest.properties")
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = TestConfiguration.class)
    public class SettingsTest {
    ...
    

    实际上,您可以直接将@EnableConfigurationProperties添加到@SpringBootTest中。
    例如:


    如果使用Spring Boot,现在您只需要:

    @RunWith(SpringRunner.class)
    @SpringBootTest
    
    没有额外的
    @ContextConfiguration
    ,没有额外的类仅用于测试
    启用自动配置
    启用配置属性
    。您不必指定要加载的配置类,它们都将被加载

    但是请确保要在
    main/resources/application.yml中读取的属性条目也存在于
    test/resources/application.yml
    中。重复是不可避免的


    另一种方式是:

  • 定义一个仅用于测试的配置类,以及同一级别的
    MyApplicationTest.java
    。该类可以为空
  • 比如:

  • 并且,在类中加载自动连线配置
  • 比如:

    基本上,你:

    • 使用特定配置来
      @EnableConfigurationProperties
      @EnableAutoConfiguration
      ,列出要加载的所有
      @ConfigurationProperties
      文件
    • 在test类中,加载这个测试配置文件,并使用Spring定义的初始化器类加载
      application.yml
      文件
    并且,将要加载的值放入
    test/resources/application.yml
    。重复是不可避免的。如果需要加载另一个文件,请使用带有位置的
    @TestProperties()
    注意
    @TestProperties
    仅支持
    .properties
    文件


    这两种方法都适用于配置类加载值

    • application.yml
      /
      application.properties
    • 或者从另一个属性文件,由
      PropertySource
      指定,如
      @PropertySource(value=“classpath:threadpool.properties”)

    重要的 Spring文档的最后注释,根据

    有些人使用ProjectLombok自动添加getter和setter。确保Lombok不会为此类类型生成任何特定构造函数,因为容器会自动使用它来实例化对象

    最后,只考虑标准JavaBean属性,不支持对静态属性的绑定

    这意味着,如果您有
    lombok@Builder
    而没有
    @noargsconstuctor
    @allargsconstuctor
    ,则不会发生属性注入,因为它只看到由
    @Builder
    创建的不可见构造函数。因此,请确保不使用任何注释,或使用所有注释

    单元测试 为了避免加载Spring上下文,我们可以使用
    Binder
    类,这也是Spring提供的

    //我的属性映射。
    映射属性=新的HashMap();
    properties.put(“我的前缀.第一个属性”,“foo”);
    properties.put(“我的前缀.secondproperty”,“bar”);
    //创建“我的地图”支持的源,您可以根据需要选择其他类型的源。
    ConfigurationPropertySource=new MapConfigurationPro
    
    @TestPropertySource(locations = "/SettingsTest.properties")
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = TestConfiguration.class)
    public class SettingsTest {
    ...
    
    @ActiveProfiles("test")
    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = TestConfiguration.class)
    @EnableConfigurationProperties
    ...
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    
    @EnableAutoConfiguration
    @EnableConfigurationProperties(value = {
            ConnectionPoolConfig.class
    })
    public class MyApplicationTestConfiguration {
    }
    
    @RunWith(SpringRunner.class)
    //@SpringBootTest // the first, easy way
    @ContextConfiguration(classes = MyApplicationTestConfiguration.class,
            initializers = ConfigFileApplicationContextInitializer.class)
    public class ConnectionPoolConfigTest {
    
        @Autowired
        private ConnectionPoolConfig config;