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

Ind*_*nes 30 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());
    }
}
Run Code Online (Sandbox Code Playgroud)

配置类:

public class TestConfiguration {
    @Bean
    @ConfigurationProperties(prefix = "test")
    public TestSettings settings (){
        return new TestSettings();
    }
}
Run Code Online (Sandbox Code Playgroud)

设置类:

public class TestSettings {
    private String property;

    public String getProperty() {
        return property;
    }

    public void setProperty(String property) {
        this.property = property;
    }
}
Run Code Online (Sandbox Code Playgroud)

资源文件夹中的属性文件包含以下条目:

test.property=TEST_PROPERTY
Run Code Online (Sandbox Code Playgroud)

在我当前的设置配置不是null,但没有可用的字段.字段不是字段的原因应该与我不使用Springboot但是Spring的事实有关.那么Springboot的运行方式是什么呢?

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

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

小智 24

您需要使用以下方法注释TestConfiguraion @EnableConfigurationProperties:

@EnableConfigurationProperties
public class TestConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "test")
    public TestSettings settings (){
        return new TestSettings();
    }
}
Run Code Online (Sandbox Code Playgroud)

你也只需要包括TestConfiguration.class@ContextConfiguration你的SettingsTest类:

@TestPropertySource(locations = "/SettingsTest.properties")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
public class SettingsTest {
...
Run Code Online (Sandbox Code Playgroud)

  • 如果使用Spring Boot和`*.yml`文件,只需删除`@ TestPropertySource`并在`@ContextConfiguration`中添加一个特殊的初始化程序,如下所示:`@ContextConfiguration(classes = TestConfiguration.class,initializers = ConfigFileApplicationContextInitializer.class) ` (6认同)

Dav*_*d H 15

几点:

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

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

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

更改代码如下:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

TestConfigurationNew.java(在测试包中):

@EnableAutoConfiguration
@ComponentScan(basePackages = { "my.package.main" })
@Configuration
public class TestConfigurationNew {
}
Run Code Online (Sandbox Code Playgroud)

现在应该按照您想要的方式工作.

  • 可能有几个原因导致在单元测试时不应创建Spring上下文.其中之一就是事实,即在测试时包括Spring上下文不是单元测试而是集成测试.使用Spring上下文运行测试(特别是如果在每个方法之后将dirties上下文设置为),则需要比正确的单元测试更多的时间来执行.此外,使用启用的Spring上下文测试单个测试方法的注入失败等边缘情况更难. (5认同)
  • @RomanVottner - 我同意,但是一旦OP表明他正在检查设置是否从属性文件中正确加载,我认为他已经进入了集成测试的领域,现在需要更全面的上下文. (2认同)

小智 12

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

@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestConfiguration.class)
@EnableConfigurationProperties
...
Run Code Online (Sandbox Code Playgroud)


Wes*_*Gun 6

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

@RunWith(SpringRunner.class)
@SpringBootTest
Run Code Online (Sandbox Code Playgroud)

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

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


另一种方式是:

  1. 定义一类仅用于测试的配置,以及MyApplicationTest.java, 在同一级别。这个类可以是空的。

喜欢:

@EnableAutoConfiguration
@EnableConfigurationProperties(value = {
        ConnectionPoolConfig.class
})
public class MyApplicationTestConfiguration {
}
Run Code Online (Sandbox Code Playgroud)
  1. 并且,在类中加载自动装配的配置。

喜欢:

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

    @Autowired
    private ConnectionPoolConfig config;
Run Code Online (Sandbox Code Playgroud)

基本上,您:

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

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


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

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

重要的

Spring 文档的最后注释,如此处所示

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

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

这意味着,如果lombok.@Builder 没有@NoArgsConstructorno@AllArgsConstructor,则不会发生属性注入,因为它只会看到由@Builder. 因此,请确保不使用任何注释,或者全部使用这些注释!