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

时间:2015-07-31 11:33:08

标签: java properties spring-boot

我想测试依赖于使用@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

在我当前的设置中,配置不为空,但没有可用的字段。 字段不是字段的原因应该与我不使用Springboot但是Spring的事实有关。 那么Springboot的方法是什么呢?

修改 我想要这样做的原因是:我有一个解析Textfiles的解析器,使用的正则表达式存储在属性文件中。 为了测试这个,我想只加载这个解析器所需的属性,这些属性位于 TestSettings 之上。

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

5 个答案:

答案 0 :(得分:23)

您需要使用@EnableConfigurationProperties注释您的TestConfiguraion,如下所示:

@EnableConfigurationProperties
public class TestConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "test")
    public TestSettings settings (){
        return new TestSettings();
    }
}

此外,您只需要在TestConfiguration.class@ContextConfiguration中加入SettingsTest

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

答案 1 :(得分:15)

几点:

  1. 您不需要" TestConfiguration"在主程序包中的类,因为它所做的就是配置" TestSettings"豆。您只需通过注释TestSettings类本身即可完成此操作。

  2. 通常,您将使用 @SpringApplicationConfiguration 注释加载测试所需的上下文,并传递Application类的名称。但是,您说您不想加载整个ApplicationContext(虽然它不清楚原因),因此您需要创建一个特殊的配置类来仅为测试加载。下面我称之为" TestConfigurationNew"避免与您最初使用的TestConfiguration类混淆。

  3. 在Spring Boot世界中,所有属性通常都保存在" application.properties"文件;但是可以将它们存储在别处。下面,我已经指定了" SettingsTest.properties"你提出的文件。请注意,您可以拥有此文件的两个副本,一个位于main / resources文件夹中,另一个位于test / resources文件夹中以供测试。

  4. 按如下方式更改代码:

    TestSettings.java(在主程序包中)

    @Configuration
    @ConfigurationProperties(prefix="test", locations = "classpath:SettingsTest.properties")
    public class TestSettings {
    
        private String property;
    
        public String getProperty() {
            return property;
        }
    
        public void setProperty(String property) {
            this.property = property;
        }
    }
    

    SettingsTest.java(在测试包中)

    @TestPropertySource(locations="classpath:SettingsTest.properties")
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = TestConfigurationNew.class)
    public class SettingsTest {
    
        @Autowired
        TestSettings settings;
    
        @Test
        public void testConfig(){
            Assert.assertEquals("TEST_PROPERTY", settings.getProperty());
        }
    }
    

    TestConfigurationNew.java(在测试包中):

    @EnableAutoConfiguration
    @ComponentScan(basePackages = { "my.package.main" })
    @Configuration
    public class TestConfigurationNew {
    }
    

    现在应该按照你想要的方式工作。

答案 2 :(得分:4)

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

@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestConfiguration.class)
@EnableConfigurationProperties
...

答案 3 :(得分:0)

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

@RunWith(SpringRunner.class)
@SpringBootTest

没有额外的@ContextConfiguration,没有额外的类,仅用于对EnableAutoConfigurationEnableConfigurationProperties的测试。您不必指定要加载的配置类,它们都将被加载。

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


另一种方法是:

  1. 在同一级别上仅为测试以及MyApplicationTest.java定义一类配置。此类可以为空。

赞:

@EnableAutoConfiguration
@EnableConfigurationProperties(value = {
        ConnectionPoolConfig.class
})
public class MyApplicationTestConfiguration {
}
  1. 然后,在该类中加载自动装配的配置。

赞:

@RunWith(SpringRunner.class)
//@SpringBootTest // the first, easy way
@ContextConfiguration(classes = MyApplicationTestConfiguration.class,
        initializers = ConfigFileApplicationContextInitializer.class)
public class ConnectionPoolConfigTest {

    @Autowired
    private ConnectionPoolConfig config;

基本上,您:

  • @EnableConfigurationProperties@EnableAutoConfiguration使用特定的配置,列出要加载的所有@ConfigurationProperties文件
  • 在测试类中,加载此测试配置文件,并使用Spring定义的初始化程序类来加载application.yml文件。

然后,将值加载到test/resources/application.yml中。重复是不可避免的。如果需要加载另一个文件,请在位置使用@TestProperties()注意@TestProperties仅支持.properties文件。


两种方法均可用于配置类加载值

  • 来自application.yml / application.properties
  • 或来自PropertySource指定的另一个属性文件,例如@PropertySource(value = "classpath:threadpool.properties")

根据here

,来自Spring文档的最后注释
  

某些人使用Project Lombok自动添加获取器和设置器。确保Lombok不会为这种类型生成任何特定的构造函数,因为容器会自动使用它来实例化该对象。

     

最后,仅考虑标准Java Bean属性,不支持对静态属性的绑定。

但是我不太理解“特殊构造函数”在这里的含义。

答案 4 :(得分:0)

单元测试

为避免必须加载Spring上下文,我们可以使用Binder类,无论如何,Spring还是used internally类。

// A map of my properties.
Map<String, String> properties = new HashMap<>();
properties.put("my-prefix.first-property", "foo");
properties.put("my-prefix.second-property", "bar");

// Creates a source backed by my map, you can chose another type of source as needed.
ConfigurationPropertySource source = new MapConfigurationPropertySource(properties)

// Binds my properties to a class that maps them.
Binder binder = new Binder(source);
BindResult<MyConfiguration> result = binder.bind("my-prefix", MyConfiguration.class);

// Should return true if bound successfully.
Assertions.assertTrue(result.isBound);

// Asserts configuration values.
MyConfiguration config = result.get();
Assertions.assertEquals("foo", config.getFirstProperty());
Assertions.assertEquals("bar", config.getSecondProperty());