[spring] YAML을 사용하는 Spring @PropertySource

Spring Boot를 사용하면 application.properties 파일을 YAML에 해당하는 파일로 바꿀 수 있습니다. 그러나 나는 내 시험에 걸림돌을 친 것 같다. 내 TestConfiguration(간단한 Java 구성)에 주석을 달면 속성 파일이 필요합니다.

예를 들어 이것은 작동하지 않습니다.
@PropertySource(value = "classpath:application-test.yml")

내 YAML 파일에 다음이있는 경우 :

db:
  url: jdbc:oracle:thin:@pathToMyDb
  username: someUser
  password: fakePassword

그리고 나는 다음과 같이 그 가치를 활용할 것입니다.

@Value("${db.username}") String username

그러나 나는 다음과 같은 오류로 끝납니다.

Could not resolve placeholder 'db.username' in string value "${db.username}"

내 테스트에서도 YAML의 장점을 어떻게 활용할 수 있습니까?



답변

Spring-boot에는 이에 대한 도우미가 있습니다.

@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)

테스트 클래스 또는 추상 테스트 수퍼 클래스의 맨 위에 있습니다.

편집 : 5 년 전에이 답변을 썼습니다. 최신 버전의 Spring Boot에서는 작동하지 않습니다. 이것이 제가 지금하는 일입니다 (필요한 경우 Kotlin을 Java로 번역하십시오).

@TestPropertySource(locations=["classpath:application.yml"])
@ContextConfiguration(
        initializers=[ConfigFileApplicationContextInitializer::class]
)

상단에 추가 된 다음

    @Configuration
    open class TestConfig {

        @Bean
        open fun propertiesResolver(): PropertySourcesPlaceholderConfigurer {
            return PropertySourcesPlaceholderConfigurer()
        }
    }

맥락에.


답변

언급했듯이 @PropertySourceyaml 파일을로드하지 않습니다. 해결 방법으로 파일을 직접로드하고로드 된 속성을 Environment.

구현 ApplicationContextInitializer:

public class YamlFileApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
  @Override
  public void initialize(ConfigurableApplicationContext applicationContext) {
    try {
        Resource resource = applicationContext.getResource("classpath:file.yml");
        YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
        PropertySource<?> yamlTestProperties = sourceLoader.load("yamlTestProperties", resource, null);
        applicationContext.getEnvironment().getPropertySources().addFirst(yamlTestProperties);
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
  }
}

테스트에 이니셜 라이저를 추가합니다.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class, initializers = YamlFileApplicationContextInitializer.class)
public class SimpleTest {
  @Test
  public test(){
    // test your properties
  }
}


답변

@PropertySourcefactory인수 로 구성 할 수 있습니다 . 따라서 다음과 같이 할 수 있습니다.

@PropertySource(value = "classpath:application-test.yml", factory = YamlPropertyLoaderFactory.class)

YamlPropertyLoaderFactory사용자 정의 속성 로더는 어디에 있습니까?

public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        if (resource == null){
            return super.createPropertySource(name, resource);
        }

        return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), null);
    }
}

https://stackoverflow.com/a/45882447/4527110에서 영감을 얻었습니다.


답변

@PropertySource속성 파일 만 지원합니다 (부트 자체가 아닌 Spring의 제한 사항입니다). JIRA에서 기능 요청 티켓 자유롭게여십시오 .


답변

또 다른 옵션은 다음을 spring.config.location통해 설정하는 것입니다 @TestPropertySource.

@TestPropertySource(properties = { "spring.config.location = classpath:<path-to-your-yml-file>" }


답변

Spring Boot 1.4부터는 Spring @SpringBootTestBoot 지원을 사용하여 통합 테스트를 부트 스트랩하여 새 주석을 사용하여 이를보다 쉽게 ​​수행 할 수 있습니다 (일반적으로 통합 테스트 설정을 단순화).

봄 블로그 에 대한 세부 사항 .

내가 말할 수있는 한, 이것은 클래스 경로에서 YAML 구성을 자동으로 선택하는 것을 포함하여 프로덕션 코드 에서처럼 Spring Boot의 외부화 된 구성 장점 의 모든 이점을 얻을 수 있음을 의미합니다 .

기본적으로이 주석은

… 먼저 @Configuration내부 클래스에서 로드 를 시도 하고 실패하면 기본 @SpringBootApplication클래스를 검색합니다 .

그러나 필요한 경우 다른 구성 클래스를 지정할 수 있습니다.

이 특별한 경우 @SpringBootTest와 결합 할 수 @ActiveProfiles( "test" )있으며 Spring은 YAML 구성을 선택합니다 application-test.yml.

@RunWith( SpringRunner.class )
@SpringBootTest
@ActiveProfiles( "test" )
public class SpringBootITest {

    @Value("${db.username}")
    private String username;

    @Autowired
    private MyBean myBean;

    ...

}

참고 : SpringRunner.class의 새 이름입니다.SpringJUnit4ClassRunner.class


답변

yaml 속성, IMHO를로드하는 방법은 두 가지 방법으로 수행 할 수 있습니다.

ㅏ. application.yml일반적으로 클래스 경로 루트 의 표준 위치에 구성을 배치 할 수 src/main/resources있으며이 yaml 속성은 언급 한 평면화 된 경로 이름으로 Spring 부트에 의해 자동으로로드됩니다.

비. 두 번째 접근 방식은 좀 더 광범위합니다. 기본적으로 다음과 같이 속성을 보유 할 클래스를 정의합니다.

@ConfigurationProperties(path="classpath:/appprops.yml", name="db")
public class DbProperties {
    private String url;
    private String username;
    private String password;
...
}

따라서 본질적으로 이것은 yaml 파일을로드하고 “db”의 루트 요소를 기반으로 DbProperties 클래스를 채우는 것입니다.

이제 모든 클래스에서 사용하려면 다음을 수행해야합니다.

@EnableConfigurationProperties(DbProperties.class)
public class PropertiesUsingService {

    @Autowired private DbProperties dbProperties;

}

이러한 접근 방식 중 하나는 Spring-boot를 사용하여 깔끔하게 작동합니다.