@Value не устанавливается через тестовый контекст, настроенный Java

У меня есть проект Maven, в котором используется Java-настроенный Spring (@Configuration и т.д.). Свойства, на которые ссылаются @Value, хранятся в разных местах, например. Tomcat context.xml.

Для тестирования я создал файл .properties, чтобы предоставить некоторые значения для компонентов и сервисов. В моем тесте JUnit (который использует тестовый контекст Spring) этот файл .properties добавляется через @PropertySource. проблема заключается в том, что значения не будут загружены из файла, вместо этого идентификатор значения устанавливается как значение, например. ${someFlag:false} (поэтому я получаю ClassCastExceptions для любого другого, кроме String). Также значение по умолчанию не будет установлено, поэтому, я думаю, значения не будут обрабатываться вообще.

Я уверен, что Spring находит этот файл, потому что, когда я изменяю значение @PropertySource, я получаю некоторое FileNotFoundException. Тем не менее, я пробовал разные варианты, чтобы указать на этот файл, все они работали (проверено переименованием, которое создало FileNotFoundException):

  • classpath:/test.properties(моя предпочтительная нотация)
  • /test.properties
  • Файл: SRC/тест/ресурсы/test.properties

Я также уверен, что сам Spring работает, потому что когда я удаляю @Value, тестируемый класс вводится через @Autowired в моем тесте, как и ожидалось.

Внизу ниже вы найдете как можно больше проблемный сценарий. Для версий и зависимостей см. Внизу 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

@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.properties

someFlag=true

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>

Ответ 1

Проблема здесь в том, что вам нужен PropertyPlaceholderConfigurer, который фактически отвечает за разрешение полей ${..}, просто добавьте еще один bean, который создает этот bean:

@Bean
public static PropertySourcesPlaceholderConfigurer propertiesResolver() {
    return new PropertySourcesPlaceholderConfigurer();
}

Ответ 2

С Spring 4 теперь можно использовать TestPropertySource:

@TestPropertySource(value="classpath:/config/test.properties")

Чтобы загрузить определенные свойства для теста junit

Ответ 3

В дополнение к Biju Kunjummen ответ:

Если вы используете @ConfigurationProperties для ввода свойств в сеттеры bean, необходимо создать ConfigurationPropertiesBindingPostProcessor (вместо PropertySourcesPlaceholderConfigurer):

@Configuration
static class PropertyConfig {
    @Bean
    public static ConfigurationPropertiesBindingPostProcessor propertiesProcessor() {
        return new ConfigurationPropertiesBindingPostProcessor();
    }
}