SpringBootTest: how to use application-test.yaml and inherit missing values from application.yaml - spring

I am trying to run an integration test using the annotations :
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
#ActiveProfiles({ "test" }).
The problem I have is that the application loads by using the spring profile "test"
I have two config files:
application.yaml
application-test.yaml
application.yaml contains:
xyz:
list:
- class-name: com.any.prod.ClassName1
jndi-name: com/ws/ClassName1
- class-name: com.any.prod.ClassName2
jndi-name: com/ws/ClassName2
and the other file doesn't contain these values.
these valuer are used by a library that i use, and not directly by my application.
when I load the test with the "test" profile enabled the values from application.yaml are not picked up. If I add the same values to application-test.yaml they are picked up during the binding process.
These are the properties that are picked up:
xyz.list[0].class-name: com.any.prod.ClassName1 (loaded from application-test.yaml)
xyz.list[0].jndi-name: com/ws/ClassName1 (loaded from application-test.yaml)
xyz.list[1].class-name: com.any.prod.ClassName2 (loaded from application-test.yaml)
xyz.list[1].jndi-name: com/ws/ClassName2 (loaded from application-test.yaml)
xyz.list (loaded from application.yaml)
Unfortunately the last entry makes the validation of the properties fail.
Does anyone has in mind what can I do to solve this mystery?
At this point my understanding of how configuration yaml files are wrong (at least for the testing case - inheritance appears to be working just fine when we deploy our app)

You can achieve this by using the annotation #TestPropertySource .

Related

In which class in the source code of spring-boot or spring is the application.yml or application.properties file processed?

In which class in the source code of spring-boot or spring is the application.yml file or application.properties processed?
For spring boot (version 2.x) the application properties are loaded from the environment into the context via a PropertySourceLoader.
In for example the spring-boot-2.6.3.jar we can find the following file:
META-INF/spring.factories
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
Where PropertiesPropertySourceLoader loads .properties and .xml files, and YamlPropertySourceLoader loads .yml and .yaml.
These are loaded with the SpringFactoriesLoader, which we can see in action in org.springframework.boot.context.config.ConfigFileApplicationListener (deprecated) or org.springframework.boot.context.config.StandardConfigDataLocationResolver (via ConfigDataEnvironmentPostProcessor -> ConfigDataEnvironment -> ConfigDataLocationResolvers) :
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
getClass().getClassLoader());
You can read in the ConfigFileApplicationListener JavaDoc that the properties are indeed loaded with this class:
EnvironmentPostProcessor that configures the context environment by loading properties from well known file locations. By default properties will be loaded from 'application.properties' and/or 'application.yml' files in the following locations:
file:./config/
file:./config/*/
file:./
classpath:config/
classpath:
...
If you're interested in context loading from the environment in spring(boot), I suggest you setup your project with maven, download the sources jars, and have a look around in the mentioned factories file. You will find more relevant code in the org.springframework.boot.env and org.springframework.boot.context (config and properties) packages.
You can find your application.yml or application.properties at the src/main/resources. You can have as many as possible configurations for your spring boot application for every case. Lets assume that you have 3 local-profiles like demo, production and server, so you made 3 configuration and assumingyou set for active profile the demo at the application.yml . I hope you get the idea. Its the first thing that actually is running before the springboot is up.
Please look the officials docs !

Different YAML configuration file for junit test using an Externalized configuration in Spring Boot

I am following a tutorial on using external configuration files for Spring Boot. I got everything to work exactly as intended but I'm having issues overriding the default YAML config for my tests.
Could someone please point me in the right direction or advice if using '#PropertySource' is the best way to load config files into the project (There is a bunch of properties and I would like to keep the application.yaml as clean as possible)
Project Structure:
src: - main/resources/foo.yml <-- always loads this one
- test/resources/foo.yml <-- never loads
What I tried:
#PropertySource(value = "classpath:foo.yml")
Doesn't load test/resoruces/foo.yml to the classpath
ActiveProfiles()
How I usually change config properties but in this case, it's not a profile so it doesn't work.
Details:
Spring boot: 2.2.7.RELEASE
Try this:
#TestPropertySource(properties = { "spring.config.location=classpath:foo.yml" })

custom properties in junit test, something like application.setDefaultProperties

I'm creating unit/integration test in Spring boot app and have difficulty to add test properties.
this is how main application get properties from src/main/resources/config.json file.
Config config = new AppConfig().config();
if (config == null) {
System.exit(1);
}
application.setDefaultProperties(config.getSpringProperties());
application.run(args);
I'd like to put test config file under src/text/resources/ and use it for integration test with MockMvc. Is there any way to do it?
config.getSpringProperties()
returns Map
Spring boot automatically resolves test properties from src/test/resources/application.properties
Update:
You can define custom properties locations with annotations like #TestPropertySource or #SpringBootTest(properties
Here some resource on the topic:
https://www.baeldung.com/properties-with-spring
Old:
Just add a file named application-test.properties or application-test.yml and annotate the test with #ActiveProfiles("test").
By this you can even have multiple profiles. Just add the #ActiveProfiles("xyz") and name the application properties file application-xyz.yml

Spring Boot JUnit and #TestPropertySource using multiple property files

Spring Boot 2.0.3.RELEASE
Have more than one properties file to deal with .. the application.properties and application-DEV.properties
using the annotation #TestPropertySource in a Junit test I can only get it to read one file:
#TestPropertySource("file:C:\\Users\\user\\eclipse-workspace\\one2one_httpCall\\src\\main\\resources\\application-DEV.properties")
works as expected
However I need two properties file I did see the locations option but did not see an example of more than one file .. tried different options but none worked:
#TestPropertySource(locations = "classpath:application-DEV.properties;classpath:application.properties")
Tried a couple of ways I am not posting and even tried using #TestPropertySource twice but error saying u cannot use it twice.
tried using #PropertySource since u can use it twice but did not work since this is a Junit test. Looked at a bunch of questions on stacktrace + others and tried but no luck.
So my question is how to use two properties files via the #TestPropertySource annotation?
If you look inside the definition of #TestPropertySource, you will see that locations is of type String []. Therefore, if you need to pass it multiple values, you must do so with an array:
#TestPropertySource(locations = { "classpath:application.properties", "classpath:application-DEV.properties" })
Also, pay attention to the order in which you declare your properties files. As stated in the TestPropertySource docs:
Each location will be added to the enclosing Environment as its own property source, in the order declared.
So you would probably want to declare your DEV properties after to avoid them being overriden by your production properties.

Override single entry in application.yml for all tests

Within the SpringBoot application you can provide the configuration via src/main/resource/application.yml.
One single entry should be overriden by the tests (see How to mock Eureka when doing Integration Tests in Spring? ). I tried to provide a test configuration with src/integration-test/resource/application.yml but it overrides the complete configuration.
eureka:
client:
enabled: false
How can I modify one entry of the configuration file for all tests?
Create a application-test.yml in src/main/resource/ with your desired configuration (eureka.client.enabled=false) and also other configurations that you require for your application to start up,
Once your application-test.yml is complete You just need to add following annotation with desired value to your test class ,
#SpringBootTest(value={"spring.profiles.active=test"})
Here spring.profiles.active=test because we have set its value to test because we want to read configurations from application-test.yml.
Hope it helps !

Resources