@Value 未通过 Java 配置的测试上下文设置
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17600605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
@Value not set via Java-configured test context
提问by Markus Ratzer
I've got a Maven project which uses Java-configured Spring (@Configuration
etc.). Properties which are referenced by @Value
are stored in different places, e.g. Tomcat's context.xml.
我有一个使用 Java 配置的 Spring(@Configuration
等)的 Maven 项目。引用的属性@Value
存储在不同的地方,例如Tomcat 的context.xml。
For testing I've created a .properties file to provide some values for the components and services. In my JUnit test (which uses a spring test context) this .properties file is added via @PropertySource
. The problemis that the values will not be loaded from the file, instead the value identifier is set as value, e.g. ${someFlag:false}
(so I get ClassCastExceptions for any other than String). Also the default value will not be set, so I think, the values won't be processed at all.
为了测试,我创建了一个 .properties 文件来为组件和服务提供一些值。在我的 JUnit 测试(使用 spring 测试上下文)中,这个 .properties 文件是通过@PropertySource
. 的问题是,这些值将不从文件中加载,而不是值标识符被设置为的值,例如${someFlag:false}
(所以我得到比串任何其他的ClassCastExceptions)。此外,不会设置默认值,因此我认为根本不会处理这些值。
I'm sure Spring finds this file because when I change the value of @PropertySource
I get some FileNotFoundException. Nevertheless I've tried different variants to point to this file an all have worked (tested by renaming which produced FileNotFoundException):
我确信 Spring 会找到这个文件,因为当我改变它的值时,@PropertySource
我得到了一些 FileNotFoundException。尽管如此,我已经尝试了不同的变体来指向这个文件,并且都有效(通过重命名测试,产生了 FileNotFoundException):
- classpath:/test.properties (my preferred notation)
- /test.properties
- file:src/test/resources/test.properties
- 类路径:/test.properties(我的首选符号)
- /test.properties
- 文件:src/test/resources/test.properties
I'm also sure that Spring itself works, because when I remove the @Value
, the class under test is injected via @Autowired
in my test as expected.
我也确定 Spring 本身可以工作,因为当我删除 时@Value
,被测类@Autowired
按预期通过我的测试注入。
Down below you'll find the problem scenario stripped down as much as possible. For versions and dependencies please see the pom.xml at the bottom.
在下面,您会发现问题场景被尽可能地精简了。有关版本和依赖项,请参阅底部的 pom.xml。
MyService.java
我的服务
package my.package.service;
// Imports
@Service
public class MyService {
@Value("${someFlag:false}")
private Boolean someFlag;
public boolean hasFlag() {
return BooleanUtils.isTrue(someFlag);
}
}
MyConfiguration.java
我的配置文件
@Configuration
@ComponentScan(basePackages = {"my.package.service"})
public class MyConfiguration {
}
MyServiceComponentTest.java
我的服务组件测试.java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {MyTestConfiguration.class})
public class MyServiceComponentTest {
@Autowired
private MyService service;
@Test
public void hasFlagReturnsTrue() {
assertThat(service.hasFlag(), is(true));
}
}
MyTestConfiguration.java
我的测试配置文件
@Configuration
@Import({MyConfiguration.class})
@PropertySource("classpath:/test.properties")
public class MyTestConfiguration {
}
src/test/resources/test.properties
src/test/resources/test.properties
someFlag=true
pom.xml
pom.xml
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>3.2.3.RELEASE</spring.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Test dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
回答by Biju Kunjummen
The issue here is you need a PropertyPlaceholderConfigurer
also which is actually responsible for resolving the ${..}
fields, just add another bean which creates this bean:
这里的问题是您还需要一个PropertyPlaceholderConfigurer
实际上负责解析${..}
字段的对象,只需添加另一个创建此 bean 的 bean:
@Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
return new PropertySourcesPlaceholderConfigurer();
}
回答by Michael
With Spring 4, it's now possible to use TestPropertySource:
在 Spring 4 中,现在可以使用TestPropertySource:
@TestPropertySource(value="classpath:/config/test.properties")
In order to load specific properties for a junit test
为了加载junit测试的特定属性
回答by Artyom Chernetsov
In addition to Biju Kunjummen answer:
除了碧菊昆珠门答:
If you use @ConfigurationProperties to inject properties into bean setters, then ConfigurationPropertiesBindingPostProcessor need to be created (instead of PropertySourcesPlaceholderConfigurer):
如果您使用@ConfigurationProperties 将属性注入 bean setter,则需要创建 ConfigurationPropertiesBindingPostProcessor(而不是 PropertySourcesPlaceholderConfigurer):
@Configuration
static class PropertyConfig {
@Bean
public static ConfigurationPropertiesBindingPostProcessor propertiesProcessor() {
return new ConfigurationPropertiesBindingPostProcessor();
}
}