问题描述
遵循中的建议,Spring Boot集成测试不会读取属性文件我创建了以下代码,目的是从JUnit测试中的属性中读取地图.(我正在使用yml格式,并使用@ConfigurationProperties而不是@Value)
Following a advice from Spring Boot integration tests doesn't read properties files I created the following code, with the intention of reading a map from properties in my JUnit test.(I am using yml format, and using @ConfigurationProperties instead of @Value)
@RunWith(SpringJUnit4ClassRunner.class)
@TestPropertySource(locations="classpath:application-test.yml")
@ContextConfiguration(classes = {PropertiesTest.ConfigurationClass.class, PropertiesTest.ClassToTest.class})
public class PropertiesTest {
@Configuration
@EnableConfigurationProperties
static class ConfigurationClass {
}
@ConfigurationProperties
static class ClassToTest {
private String test;
private Map<String, Object> myMap = new HashMap<>();
public String getTest() {
return test;
}
public void setTest(String test) {
this.test = test;
}
public Map<String, Object> getMyMap() {
return myMap;
}
}
@Autowired
private ClassToTest config;
@Test
public void testStringConfig() {
Assert.assertEquals(config.test, "works!");
}
@Test
public void testMapConfig() {
Assert.assertEquals(config.myMap.size(), 1);
}
}
我的测试配置(在application-test.yml中):
My test configuration (in application-test.yml):
test: works!
myMap:
aKey: aVal
aKey2: aVal2
奇怪的是,字符串有效!"已成功从配置文件中读取,但未填充地图.
Strangely, the String "works!" is successfully read from the config file, but the map is not populated.
我想念什么?
注意:添加地图设置器会导致以下异常:
Note: adding a map setter causes the following exception:
Caused by: org.springframework.validation.BindException: org.springframework.boot.bind.RelaxedDataBinder$RelaxedBeanPropertyBindingResult: 1 errors
Field error in object 'target' on field 'myMap': rejected value []; codes [typeMismatch.target.myMap,typeMismatch.myMap,typeMismatch.java.util.Map,typeMismatch]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [target.myMap,myMap]; arguments []; default message [myMap]]; default message [Failed to convert property value of type 'java.lang.String' to required type 'java.util.Map' for property 'myMap'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'java.util.Map' for property 'myMap': no matching editors or conversion strategy found]
at org.springframework.boot.bind.PropertiesConfigurationFactory.checkForBindingErrors(PropertiesConfigurationFactory.java:359)
at org.springframework.boot.bind.PropertiesConfigurationFactory.doBindPropertiesToTarget(PropertiesConfigurationFactory.java:276)
at org.springframework.boot.bind.PropertiesConfigurationFactory.bindPropertiesToTarget(PropertiesConfigurationFactory.java:240)
at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:330)
... 42 more
推荐答案
与调试器一起度过了一段美好的时光后,我相信这是TestPropertySourceUtils.addPropertiesFilesToEnvironment()
中的错误/缺失功能:
After some wonderful time with a debugger,I believe that this is a bug / missing feature in TestPropertySourceUtils.addPropertiesFilesToEnvironment()
:
try {
for (String location : locations) {
String resolvedLocation = environment.resolveRequiredPlaceholders(location);
Resource resource = resourceLoader.getResource(resolvedLocation);
environment.getPropertySources().addFirst(new ResourcePropertySource(resource));
}
}
ResourcePropertySource
仅能处理.properties
文件,而不能处理.yml
.在常规应用中,YamlPropertySourceLoader
已注册并且可以处理.yml
.
ResourcePropertySource
can only deal with .properties
files and not .yml
.In regular app, YamlPropertySourceLoader
registered and can deal with .yml
.
请注意:TestPropertySourceUtils.addPropertiesFilesToEnvironment()
的调用者是:
As a note:TestPropertySourceUtils.addPropertiesFilesToEnvironment()
is called by:
org.springframework.test.context.support.DelegatingSmartContextLoader.prepareContext()
(继承自AbstractContextLoader
)
DelegatingSmartContextLoader
是您收到的默认上下文加载器.(实际上@ContextConfiguration
指定了一个接口,但是AbstractTestContextBootstrapper.resolveContextLoader()
将其更改为具体的类)
DelegatingSmartContextLoader
is the default context loader you receive if no loader is specified in @ContextConfiguration
.(in fact @ContextConfiguration
specifies an interface, but AbstractTestContextBootstrapper.resolveContextLoader()
changes it to a concrete class)
要解决此问题,我将配置更改为application-test.properties
并在我的测试中使用了该文件.
To resolve the problem, I changed my configuration to application-test.properties
and used that file in my test.
test=works!
myMap.aKey: aVal
另一条评论:不需要地图上的二传手:
Another comment: the setter on the map is NOT needed:
这篇关于在测试中使用Spring @ConfigurationProperties读取地图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!