Spring @PropertySource using YAML
Spring Boot pozwala nam zastąpić naszą aplikację.pliki właściwości z odpowiednikami YAML. Jednak wydaje mi się, że mam problem z moimi testami. Jeśli dodam adnotację do mojego TestConfiguration
(prostej konfiguracji Javy), oczekuje on pliku właściwości.
Na przykład to nie działa:
@PropertySource(value = "classpath:application-test.yml")
Jeśli mam to w moim pliku YAML:
db:
url: jdbc:oracle:thin:@pathToMyDb
username: someUser
password: fakePassword
I wykorzystałbym te wartości czymś takim:
@Value("${db.username}") String username
Jednak kończę z i błąd tak:
Could not resolve placeholder 'db.username' in string value "${db.username}"
Jak mogę wykorzystać dobroć YAML również w moich testach?
17 answers
Spring-boot ma do tego helpera, wystarczy dodać
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
Na górze Twoich klas testowych lub abstrakcyjnej klasy testowej.
Edit: napisałem tę odpowiedź pięć lat temu. Nie działa z najnowszymi wersjami Spring Boot. To jest to, co robię teraz (proszę przetłumaczyć Kotlina na Javę, jeśli to konieczne):
@TestPropertySource(locations=["classpath:application.yml"])
@ContextConfiguration(
initializers=[ConfigFileApplicationContextInitializer::class]
)
Dodaje się do góry, następnie
@Configuration
open class TestConfig {
@Bean
open fun propertiesResolver(): PropertySourcesPlaceholderConfigurer {
return PropertySourcesPlaceholderConfigurer()
}
}
Do kontekstu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-25 13:45:22
Jak wspomniano @PropertySource
nie wczytuje pliku yaml. Jako obejście Załaduj plik samodzielnie i dodaj załadowane właściwości do 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);
}
}
}
Dodaj swój inicjalizator do testu:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class, initializers = YamlFileApplicationContextInitializer.class)
public class SimpleTest {
@Test
public test(){
// test your properties
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-10 01:38:46
@PropertySource
można skonfigurować za pomocą argumentu factory
. Więc możesz zrobić coś w stylu:
@PropertySource(value = "classpath:application-test.yml", factory = YamlPropertyLoaderFactory.class)
Gdzie YamlPropertyLoaderFactory
jest Twoim niestandardowym loaderem właściwości:
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);
}
}
Inspired by https://stackoverflow.com/a/45882447/4527110
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-18 02:28:27
@PropertySource
obsługuje tylko pliki właściwości (jest to ograniczenie od Springa, a nie sam Boot). Możesz otworzyć zgłoszenie żądania funkcji w JIRA .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-22 07:35:11
Inną opcją jest ustawienie spring.config.location
przez @TestPropertySource
:
@TestPropertySource(properties = { "spring.config.location = classpath:<path-to-your-yml-file>" }
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-26 18:42:20
Od wersji Spring Boot 1.4, możesz użyć nowej adnotacji @SpringBootTest
, aby to łatwiej osiągnąć (i ogólnie uprościć konfigurację testów integracyjnych)poprzez bootstrapowanie testów integracyjnych przy użyciu obsługi Spring Boot.
Szczegóły na wiosennym blogu.
Z tego co wiem, oznacza to, że otrzymujesz wszystkie zalety Spring Boot ' s externalized Config goodness tak jak w Twoim kodzie produkcyjnym, w tym automatyczne pobieranie konfiguracji YAML z classpath.
Domyślnie ta adnotacja będzie
... pierwsza próba załadowania
@Configuration
z dowolnej klasy wewnętrznej, a jeśli to się nie powiedzie, będzie szukać podstawowej@SpringBootApplication
klasy.
Ale w razie potrzeby możesz określić inne klasy konfiguracji.
W tym konkretnym przypadku, możesz połączyć @SpringBootTest
z @ActiveProfiles( "test" )
i Spring odbierze konfigurację YAML, pod warunkiem, że będzie ona zgodna z normalnymi standardami nazw ROZRUCHOWYCH (np. application-test.yml
).
@RunWith( SpringRunner.class )
@SpringBootTest
@ActiveProfiles( "test" )
public class SpringBootITest {
@Value("${db.username}")
private String username;
@Autowired
private MyBean myBean;
...
}
Uwaga: SpringRunner.class
jest nowa nazwa dla SpringJUnit4ClassRunner.class
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-08 17:39:09
Podejście do ładowania właściwości yaml, IMHO można zrobić na dwa sposoby:
A. Możesz umieścić konfigurację w standardowej lokalizacji - application.yml
w katalogu głównym classpath - zazwyczaj src/main/resources
i ta właściwość yaml powinna zostać automatycznie załadowana przez Spring boot z nazwą spłaszczonej ścieżki, o której wspomniałeś.
B. drugie podejście jest nieco bardziej rozbudowane, zasadniczo zdefiniuj klasę, która przechowuje Twoje właściwości w ten sposób:
@ConfigurationProperties(path="classpath:/appprops.yml", name="db")
public class DbProperties {
private String url;
private String username;
private String password;
...
}
Więc zasadniczo mówi się, że Załaduj plik yaml i uzupełnij klasę DbProperties w oparciu o główny element "db".
Teraz, aby użyć go w dowolnej klasie, musisz to zrobić:
@EnableConfigurationProperties(DbProperties.class)
public class PropertiesUsingService {
@Autowired private DbProperties dbProperties;
}
Każda z tych metod powinna działać dla Ciebie czysto przy użyciu Spring-boot.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-22 01:36:50
Znalazłem obejście używając @ActiveProfiles("test")
i dodając Test aplikacji.plik yml do src / test/resources.
Skończyło się tak:
@SpringApplicationConfiguration(classes = Application.class, initializers = ConfigFileApplicationContextInitializer.class)
@ActiveProfiles("test")
public abstract class AbstractIntegrationTest extends AbstractTransactionalJUnit4SpringContextTests {
}
Aplikacja pliku-test.yml zawiera tylko właściwości, które chcę zastąpić z aplikacji.yml (który można znaleźć w src / main / resources).
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-16 15:58:15
To dlatego, że nie skonfigurowałeś snakeyml. sprężynowe buty są wyposażone w funkcję konfiguracji @EnableAutoConfiguration. jest też konfiguracja snakeyml, gdy wywołujesz tę adnotację..
This is my way:
@Configuration
@EnableAutoConfiguration
public class AppContextTest {
}
Oto mój test:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(
classes = {
AppContextTest.class,
JaxbConfiguration.class,
}
)
public class JaxbTest {
//tests are ommited
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-12 07:33:30
Musiałem wczytać kilka właściwości do mojego kodu i działa to Z spring-boot 1.3.0.RELEASE
@Autowired
private ConfigurableListableBeanFactory beanFactory;
// access a properties.yml file like properties
@Bean
public PropertySource properties() {
PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
YamlPropertiesFactoryBean yaml = new YamlPropertiesFactoryBean();
yaml.setResources(new ClassPathResource("properties.yml"));
propertySourcesPlaceholderConfigurer.setProperties(yaml.getObject());
// properties need to be processed by beanfactory to be accessible after
propertySourcesPlaceholderConfigurer.postProcessBeanFactory(beanFactory);
return propertySourcesPlaceholderConfigurer.getAppliedPropertySources().get(PropertySourcesPlaceholderConfigurer.LOCAL_PROPERTIES_PROPERTY_SOURCE_NAME);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-10 18:56:12
Ładowanie niestandardowego pliku yml z konfiguracją wielu profili podczas wiosennego rozruchu.
1) Dodaj właściwość bean z SpringBootApplication Uruchom się w następujący sposób
@SpringBootApplication
@ComponentScan({"com.example.as.*"})
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
@Bean
@Profile("dev")
public PropertySourcesPlaceholderConfigurer propertiesStage() {
return properties("dev");
}
@Bean
@Profile("stage")
public PropertySourcesPlaceholderConfigurer propertiesDev() {
return properties("stage");
}
@Bean
@Profile("default")
public PropertySourcesPlaceholderConfigurer propertiesDefault() {
return properties("default");
}
/**
* Update custom specific yml file with profile configuration.
* @param profile
* @return
*/
public static PropertySourcesPlaceholderConfigurer properties(String profile) {
PropertySourcesPlaceholderConfigurer propertyConfig = null;
YamlPropertiesFactoryBean yaml = null;
propertyConfig = new PropertySourcesPlaceholderConfigurer();
yaml = new YamlPropertiesFactoryBean();
yaml.setDocumentMatchers(new SpringProfileDocumentMatcher(profile));// load profile filter.
yaml.setResources(new ClassPathResource("env_config/test-service-config.yml"));
propertyConfig.setProperties(yaml.getObject());
return propertyConfig;
}
}
2) Konfiguracja obiektu pojo Java w następujący sposób
@Component
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_NULL)
@ConfigurationProperties(prefix = "test-service")
public class TestConfig {
@JsonProperty("id")
private String id;
@JsonProperty("name")
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3) Utwórz niestandardowy yml (i umieść go pod ścieżką zasobów w następujący sposób, Nazwa pliku YML: test-service-config.yml
Np. Config w pliku yml.
test-service:
id: default_id
name: Default application config
---
spring:
profiles: dev
test-service:
id: dev_id
name: dev application config
---
spring:
profiles: stage
test-service:
id: stage_id
name: stage application config
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-19 21:56:57
Byłem w szczególnej sytuacji, w której nie mogłem załadować klasy @ConfigurationProperties z powodu niestandardowego nazewnictwa właściwości plików. Na koniec działa tylko (dzięki @ Mateusz Balbus):
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
import org.apache.commons.io.IOUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.bind.Bindable;
import org.springframework.boot.context.properties.bind.Binder;
import org.springframework.boot.env.YamlPropertySourceLoader;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.Resource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {MyTest.ContextConfiguration.class})
public class MyTest {
@TestConfiguration
public static class ContextConfiguration {
@Autowired
ApplicationContext applicationContext;
@Bean
public ConfigurationPropertiesBean myConfigurationPropertiesBean() throws IOException {
Resource resource = applicationContext.getResource("classpath:my-properties-file.yml");
YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader();
List<PropertySource<?>> loadedSources = sourceLoader.load("yamlTestProperties", resource);
PropertySource<?> yamlTestProperties = loadedSources.get(0);
ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment)applicationContext.getEnvironment();
configurableEnvironment.getPropertySources().addFirst(yamlTestProperties);
Binder binder = Binder.get(applicationContext.getEnvironment());
ConfigurationPropertiesBean configurationPropertiesBean = binder.bind("my-properties-file-prefix", Bindable.of(ConfigurationPropertiesBean.class)).get();
return configurationPropertiesBean;
}
}
@Autowired
ConfigurationPropertiesBean configurationPropertiesBean;
@Test
public void test() {
configurationPropertiesBean.getMyProperty();
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-11 15:06:21
<dependency>
<groupId>com.github.yingzhuo</groupId>
<artifactId>spring-boot-stater-env</artifactId>
<version>0.0.3</version>
</dependency>
Zapraszam do korzystania z mojej biblioteki. Teraz yaml, toml, hocon jest obsługiwana.
Źródło: github.com
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-06 03:00:25
Nie jest to odpowiedź na pierwotne pytanie, ale alternatywne rozwiązanie dla potrzeby posiadania innej konfiguracji w teście...
Zamiast @PropertySource
możesz użyć -Dspring.config.additional-location=classpath:application-tests.yml
.
Należy pamiętać, że przyrostek tests
nie oznacza profilu...
W tym jednym pliku YAML można określić wiele profili, które mogą dziedziczyć po sobie, Czytaj więcej tutaj - właściwość rozwiązująca dla wielu profili sprężynowych (konfiguracja yaml)
Wtedy można określić w twój test, że aktywne profile (za pomocą @ActiveProfiles("profile1,profile2")
) są profile1,profile2
Gdzie profile2
po prostu nadpisuje (niektóre, nie trzeba nadpisywać wszystkich) właściwości z profile1
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-04 12:56:29
Próbowałem wszystkich wymienionych pytań, ale wszystkie nie działają na moje zadanie: używanie konkretnego pliku yaml do jakiegoś testu jednostkowego. W moim przypadku działa to tak:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(initializers = {ConfigFileApplicationContextInitializer.class})
@TestPropertySource(properties = {"spring.config.location=file:../path/to/specific/config/application.yml"})
public class SomeTest {
@Value("${my.property.value:#{null}}")
private String value;
@Test
public void test() {
System.out.println("value = " + value);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-14 14:28:29
Miałem podobny problem. Używam SpringBoot 2.4.1
. Jeśli napotkasz podobny problem, tzn. nie możesz załadować plików yml
, spróbuj dodać adnotację na poziomie klasy w swoim teście.
@SpringJUnitConfig(
classes = { UserAccountPropertiesTest.TestConfig.class },
initializers = { ConfigDataApplicationContextInitializer.class }
)
class UserAccountPropertiesTest {
@Configuration
@EnableConfigurationProperties(UserAccountProperties.class)
static class TestConfig { }
@Autowired
UserAccountProperties userAccountProperties;
@Test
void getAccessTokenExpireIn() {
assertThat(userAccountProperties.getAccessTokenExpireIn()).isEqualTo(120);
}
@Test
void getRefreshTokenExpireIn() {
assertThat(userAccountProperties.getRefreshTokenExpireIn()).isEqualTo(604800);
}
}
ConfigDataApplicationContextInitializer
z import org.springframework.boot.test.context.ConfigDataApplicationContextInitializer;
jest Tym, który "pomaga" przetłumaczyć yml
pliki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-01 07:10:10
Nie ma potrzeby dodawania takich jak YamlPropertyLoaderFactory lub YamlFileApplicationContextInitializer. Powinieneś zmienić swój pomysł. zupełnie jak wspólny projekt wiosenny. Nie używam Javy config. Tylko *.xml
Wykonaj następujące kroki:
Wystarczy dodać applicationContext.XML like
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd"
default-autowire="byName">
<context:property-placeholder location="classpath*:*.yml"/>
</beans>
Następnie dodaj
@ImportResource({"classpath:applicationContext.xml"})
Do twojego ApplicationMainClass
.
To może pomóc zeskanować aplikację-test.yml
db:
url: jdbc:oracle:thin:@pathToMyDb
username: someUser
password: fakePassword
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-24 09:29:37