我想测试依赖于使用@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启动配置对我来说似乎有点太多了。这就是为什么我问是否有可能只加载一个具有属性的类。
答案 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)
几点:
您不需要" TestConfiguration"在主程序包中的类,因为它所做的就是配置" TestSettings"豆。您只需通过注释TestSettings类本身即可完成此操作。
通常,您将使用 @SpringApplicationConfiguration 注释加载测试所需的上下文,并传递Application类的名称。但是,您说您不想加载整个ApplicationContext(虽然它不清楚原因),因此您需要创建一个特殊的配置类来仅为测试加载。下面我称之为" TestConfigurationNew"避免与您最初使用的TestConfiguration类混淆。
在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;
}
}
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
,没有额外的类,仅用于对EnableAutoConfiguration
和EnableConfigurationProperties
的测试。您不必指定要加载的配置类,它们都将被加载。
但是,请确保您要在main/resources/application.yml
中读取的属性条目也出现在test/resources/application.yml
中。重复是不可避免的。
另一种方法是:
MyApplicationTest.java
定义一类配置。此类可以为空。赞:
@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;
基本上,您:
@EnableConfigurationProperties
和@EnableAutoConfiguration
使用特定的配置,列出要加载的所有@ConfigurationProperties
文件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());