@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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 02:26:04  来源:igfitidea点击:

@Value not set via Java-configured test context

javaspringtestingpropertiesjunit

提问by Markus Ratzer

I've got a Maven project which uses Java-configured Spring (@Configurationetc.). Properties which are referenced by @Valueare 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 @PropertySourceI 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 @Autowiredin 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 PropertyPlaceholderConfigureralso 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();
    }
}