Spring Boot nous permet de remplacer nos fichiers application.properties par des équivalents YAML. Cependant, je semble avoir un problème avec mes tests. Si TestConfiguration
mon TestConfiguration
(une simple configuration Java), il attend un fichier de propriétés.
Par exemple, cela ne fonctionne pas: @PropertySource(value = "classpath:application-test.yml")
Si je l’ai dans mon fichier YAML:
db: url: jdbc:oracle:thin:@pathToMyDb username: someUser password: fakePassword
Et je tirerais parti de ces valeurs avec quelque chose comme ceci:
@Value("${db.username}") Ssortingng username
Cependant, je finis avec et erreur comme ça:
Could not resolve placeholder 'db.username' in ssortingng value "${db.username}"
Comment puis-je également tirer parti des bienfaits de YAML dans mes tests?
Spring-boot a une aide pour cela, il suffit d’append
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class)
en haut de vos classes de test ou une super-classe de test abstraite.
Comme il a été mentionné, @PropertySource
ne charge pas le fichier yaml. Pour contourner le problème, chargez le fichier vous-même et ajoutez les propriétés chargées à l’ Environment
.
Implémentation ApplicationContextInitializer
:
public class YamlFileApplicationContextInitializer implements ApplicationContextInitializer { @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); } } }
Ajoutez votre initialiseur à votre test:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = Application.class, initializers = YamlFileApplicationContextInitializer.class) public class SimpleTest { @Test public test(){ // test your properties } }
@PropertySource
ne supporte que les fichiers de propriétés (c’est une limitation de Spring, pas Boot elle-même). N’hésitez pas à ouvrir un ticket de demande de fonctionnalité dans JIRA .
L’approche pour charger les propriétés de l’igname, IMHO peut être faite de deux manières:
une. Vous pouvez placer la configuration dans un emplacement standard – application.yml
dans la racine du chemin de classe – généralement src/main/resources
et cette propriété yaml devrait être automatiquement chargée par Spring boot avec le nom de chemin aplati que vous avez mentionné.
b. La seconde approche est un peu plus étendue, définissant essentiellement une classe pour contenir vos propriétés de cette manière:
@ConfigurationProperties(path="classpath:/appprops.yml", name="db") public class DbProperties { private Ssortingng url; private Ssortingng username; private Ssortingng password; ... }
Donc essentiellement cela dit que charger le fichier yaml et remplir la classe DbProperties basée sur l’élément racine de “db”.
Maintenant, pour l’utiliser dans n’importe quelle classe, vous devrez le faire:
@EnableConfigurationProperties(DbProperties.class) public class PropertiesUsingService { @Autowired private DbProperties dbProperties; }
Chacune de ces approches devrait fonctionner pour vous de manière propre en utilisant Spring-boot.
Depuis Spring Boot 1.4, vous pouvez utiliser la nouvelle annotation @SpringBootTest
pour y parvenir plus facilement (et pour simplifier la configuration de vos tests d’intégration en général) en amorçant vos tests d’intégration à l’aide de la prise en charge de Spring Boot.
Détails sur le blog de spring .
Autant que je sache, cela signifie que vous obtenez tous les avantages de la qualité de configuration externalisée de Spring Boot, tout comme dans votre code de production, y compris la saisie automatique de la configuration YAML dans le classpath.
Par défaut, cette annotation sera
… d’abord essayer de charger
@Configuration
partir de n’importe quelle classe interne, et si cela échoue, il recherchera votre classe@SpringBootApplication
principale.
mais vous pouvez spécifier d’autres classes de configuration si nécessaire.
Pour ce cas particulier, vous pouvez combiner @SpringBootTest
avec @ActiveProfiles( "test" )
et Spring récupérera votre configuration YAML, à condition qu’elle respecte les normes de dénomination de démarrage normales ( application-test.yml
).
@RunWith( SpringRunner.class ) @SpringBootTest @ActiveProfiles( "test" ) public class SpringBootITest { @Value("${db.username}") private Ssortingng username; @Autowired private MyBean myBean; ... }
Remarque: SpringRunner.class
est le nouveau nom de SpringJUnit4ClassRunner.class
Une autre option consiste à définir le spring.config.location
via @TestPropertySource
:
@TestPropertySource(properties = { "spring.config.location = classpath:" }
J’ai trouvé une solution en utilisant @ActiveProfiles("test")
et en ajoutant un fichier application-test.yml à src / test / resources.
Cela a fini par ressembler à ceci:
@SpringApplicationConfiguration(classes = Application.class, initializers = ConfigFileApplicationContextInitializer.class) @ActiveProfiles("test") public abstract class AbstractIntegrationTest extends AbstractTransactionalJUnit4SpringContextTests { }
Le fichier application-test.yml ne contient que les propriétés que je veux remplacer depuis application.yml (que vous pouvez trouver dans src / main / resources).
@PropertySource
peut être configuré par argument de factory
. Vous pouvez donc faire quelque chose comme:
@PropertySource(value = "classpath:application-test.yml", factory = YamlPropertyLoaderFactory.class)
Où YamlPropertyLoaderFactory
est votre chargeur de propriété personnalisé:
public class YamlPropertyLoaderFactory extends DefaultPropertySourceFactory { @Override public PropertySource> createPropertySource(Ssortingng name, EncodedResource resource) throws IOException { if (resource == null){ return super.createPropertySource(name, resource); } return new YamlPropertySourceLoader().load(resource.getResource().getFilename(), resource.getResource(), null); } }
Inspiré par https://stackoverflow.com/a/45882447/4527110
c’est parce que vous n’avez pas configuré snakeyml. botte à ressort avec fonction @EnableAutoConfiguration. il y a aussi la configuration de snakeyml quand vous appelez cette annotation.
c’est mon chemin:
@Configuration @EnableAutoConfiguration public class AppContextTest { }
voici mon test:
@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration( classes = { AppContextTest.class, JaxbConfiguration.class, } ) public class JaxbTest { //tests are ommited }
J’avais besoin de lire certaines propriétés dans mon code et cela fonctionne avec 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); }
Chargement d’un fichier yml personnalisé avec la configuration de plusieurs profils dans Spring Boot.
1) Ajoutez le bean de propriété avec SpringBootApplication comme suit
@SpringBootApplication @ComponentScan({"com.example.as.*"}) public class TestApplication { public static void main(Ssortingng[] 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(Ssortingng 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) Configurez l’object Java pojo comme suit
@Component @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(Include.NON_NULL) @ConfigurationProperties(prefix = "test-service") public class TestConfig { @JsonProperty("id") private Ssortingng id; @JsonProperty("name") private Ssortingng name; public Ssortingng getId() { return id; } public void setId(Ssortingng id) { this.id = id; } public Ssortingng getName() { return name; } public void setName(Ssortingng name) { this.name = name; } }
3) Créez le yml personnalisé (et placez-le sous le chemin de ressource comme suit, nom du fichier YML: test-service-config.yml
Par exemple Config dans le fichier 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
Améliorer la réponse de Mateusz Balbus .
Classe YamlFileApplicationContextInitializer
modifiée où l’emplacement YAML est défini par classe de test. Cela ne fonctionne pas par test, malheureusement.
public abstract class YamlFileApplicationContextInitializer implements ApplicationContextInitializer { /*** * Return location of a YAML file, eg: classpath:file.yml * * @return YAML file location */ protected abstract Ssortingng getResourceLocation(); @Override public void initialize(ConfigurableApplicationContext applicationContext) { try { Resource resource = applicationContext.getResource(getResourceLocation()); YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader(); PropertySource> yamlTestProperties = sourceLoader.load("yamlTestProperties", resource, null); applicationContext.getEnvironment().getPropertySources().addFirst(yamlTestProperties); } catch (IOException e) { throw new RuntimeException(e); } } }
Usage:
Créez la sous-classe de YamlFileApplicationContextInitializer
avec la méthode getResourceLocation()
définie et ajoutez cette sous-classe à l’annotation @SpringApplicationConfiguration
.
Je pense que le plus simple est de faire de la classe de test elle-même une sous-classe spécifique comme dans l’exemple suivant.
@RunWith(SpringRunner.class) @SpringApplicationConfiguration(classes = Application.class, initializers = SimpleTest.class) public class SimpleTest extends YamlFileApplicationContextInitializer { @Override protected Ssortingng getResourceLocation() { return "classpath:test_specific.yml"; } @Test public test(){ // test your properties } }