Spring boot - test properties overriden with prod properties - spring-boot

My test properties are overriden with those placed in production properties.
At the very beggining I had both named application.yml but it didn't work, so I have changed like told in this post to application-test.yml and use profile.
Now it looks like bellow (kotlin):
#SpringBootTest
#ExtendWith(SpringExtension::class)
#ContextConfiguration(classes = [InvalidPropertiesApplication::class])
#ActiveProfiles("test")
#TestPropertySource(locations = ["classpath:application.yml"])
class InvalidPropertiesApplicationTests {
#Test
fun contextLoads(#Autowired users: Users) {
assertEquals("TEST", users.file)
}
}
in src/main/resources/application.yml I have only set this property
to PRODUCTION, in src/test/resources/application-test.yml to TEST.
And this test fails.
Full example can be found at github
Thx in advance.

Properties loaded with #TestPropertySource have a higher precedence than all other property sources in your example. And "classpath:application.yml" refers to src/main/resources/application.yml.
Order: #TestPropertySource > application-{profile}.properties/yaml > application.properties/yaml
See also the Spring Boot Reference Guide.

Related

Spring Test : why cannot access application.properties?

I'm building an extremly easy Spring Boot application. It has no code, just a simple test :
#RunWith(SpringRunner.class)
#SpringBootTest
public class MyTest {
#Value("${my.key}")
private String key;
#Test
public void test() {
System.out.println(key);
}
}
my.key is defined inside src/main/resources/application.properties (in main/ not test/)
The test doesn't pass because cannot find my.key property (but if I put this property inside src/test/resources/application.properties it works)
I'm sure I have seen plenty of Spring Boot applications where test classes read properties from /main/resources/application.properties
But here it does not work.
If you also add a application.properties file inside src/test/resources, this will "override" the one in src/main/resources, and hence none of the keys you define in your "production" properties file will be seen.
So either remove your application.properties in src/test/resources to use your property file in src/main/resources or define your values there.
You can use #TestPropertySource to override the location of your application.properties.
#RunWith(SpringRunner.class)
#SpringBootTest
#TestPropertySource(locations="classpath:application.properties")
public class MyTest {
}
For further help on how to use it, please check here

Spring Boot is not loading the properties from a YML file

My test file is :
#ActiveProfiles("test")
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class MyApplicationTest {
#InjectMocks
#Autowired
protected MyController myController;
}
My Controller file is:
#RestController
#RequestMapping(value="${app.base-path}") // Unable to load this property
public class MyController {
}
I have tried #TestPropertySource but did not work.
The SpringBootApplication works fine.
This is not the case with #Value annotation.
Fields decorated with #Value annotation works just fine.
Did you name your .yml file as application.yml and put it on the src/main/resources or src/test/resources?
Placing the application.yml file on those folders will automatically add it to the classpath so you can access this file properties at runtime.
By default, Spring Boot will try to load application.yml and application-{profilename}.yml available on classpath, so you could try with application-test.yml (it will eliminate the problem with defining profiles in one file - maybe it causes your problem).
Also, you could try with bootstrap.yml, which is loaded before application.yml.

Spring boot tests - Can't find test properties

I have a spring boot project and it works great. I now want to write tests for my application and I am running into some configuration headaches.
Spring boot created a test class for me called ApplicationTests. It's real simple and it looks like this:
#RunWith(SpringRunner.class)
#SpringBootTest
public class DuurzaamApplicationTests {
#Test
public void contextLoads() {
}
}
Now when I start the tests I get this error:
java.lang.IllegalArgumentException: Could not resolve placeholder 'company.upload' in value "${company.upload}"
I have a properties.yml file in the src/test/resources directory and for some reason it isn't loaded. I have tried all different kind of annotations from examples on the Internet and yet none of them work.
How can I tell spring boot tests to use an application.yml file to load the properties from?
We can use #TestPropertySource or #PropertySource to load the properties file.
Example:
#RunWith(SpringRunner.class)
#SpringBootTest
#TestPropertySource("classpath:properties.yml")
#ActiveProfiles("test")
public class DuurzaamApplicationTests {
#Test
public void contextLoads() {
}
}
Docs: https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/TestPropertySource.html
To my surprise, when you load properties files in Spring Boot Test, .yml is not supported. It's noted in the documentation, although implicitly.
From the link above:
https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/context/TestPropertySource.html
Supported File Formats
Both traditional and XML-based properties file formats are supported — for example, "classpath:/com/example/test.properties" or "file:/path/to/file.xml".
.yml is not mentioned.
And, after changing my .yml to .properties and rewrite the values in xx.xx.xx=value form, the key-values pairs can be read correctly.
So strange.
EDIT:
Now I find a ticket address this issue; seems a long-known bug in Spring.
https://github.com/spring-projects/spring-framework/issues/18486
#PropertySource and #TestPropertySource do not work with YAML. See this.
I also tested it myself. Try creating 2 files - *.yml and *.properties and see it for yourself.
To make *.yml work most people use #SpringBootTest, but if it's not what you want and you would like to use #ContextConfiguration instead, you are in for a bit of surprise.
For me the above solutions did not work and any environment variables were still overriding the test properties defined in #TestPropertySource even though https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html indicates that this source should have higher precedence than environment variables. The only solution that worked for me was to manually define a PropertyPlaceholderConfigurer bean in a test configuration class and set it with highest precedence.
This was with Spring Boot 1.5.15.RELEASE
#Configuration
#TestPropertySource(properties = "/application-test.properties")
#Slf4j
public class IntegrationTestConfiguration {
#Bean
public static PropertyPlaceholderConfigurer properties() {
PropertyPlaceholderConfigurer ppc
= new PropertyPlaceholderConfigurer();
Resource[] resources = new ClassPathResource[]
{ new ClassPathResource( "/application-test.properties" ) };
ppc.setLocations( resources );
ppc.setIgnoreUnresolvablePlaceholders( true );
ppc.setOrder( Ordered.HIGHEST_PRECEDENCE );
return ppc;
}
/// ....
#RunWith( SpringRunner.class )
#ActiveProfiles( "test" )
#Import( IntegrationTestConfiguration.class )
#SpringBootTest( webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT )
public class MyTest {
I had the same error message, my problem was a application.properties in src\test\resources which was missing the new properties
Sometimes your application-test.properties file can't be found because it is in a subfolder off the class path.
for example this may not be found, because the file is actually not directly in the class path.
#TestPropertySource("classpath:application-test.properties")
but this will be found if the file is in the config folder off of a path in the class path
#TestPropertySource("classpath:config/application-test.properties")
We can use annotation of #ActiveProfiles("test") that support application-test.yml or application-test.properties

Datasource Configuration for JUnit using Maven

We’ve configured multiple Spring Boot profiles in our application and data source changes according to the profile activated.
We’ve separate data source for Junit Tests. Now, we want to use this data source for JUnit Tests irrespective of the profile activated.
We were able to achieve this using #TestPropertySource in every test class but we need this configuration in one place in pom.xml. I’m aware of maven-surefire-plugin which is used to execute Junit Tests but not sure how we can configure particular data source there.
Is there any way to achieve this?
Any help would be much appreciated.
One simple way of doing this is to create profile-dependable configuratons as wrappers over normal configurations, like this:
Profile 1:
#Profile("ds1")
#Import(Ds1Configuration.class)
public class Ds1ProfileConfiguration {}
Profile 2:
#Profile("ds2")
#Import(Ds2Configuration.class)
public class Ds2ProfileConfiguration {}
where the imported configurations contain actual bean definitions:
public class Ds1Configuration {
#Bean
public DataSource dataSource(){...}
}
and
public class Ds2Configuration {
#Bean
public DataSource dataSource(){...}
}
This will separate your profiles and configurations, so you will be able to use these in your tests:
#SpringBootTest(classes = Ds2Configuration.class)

Defining profile dependant YAML properties in Spring Boot 1.4

When defining properties in YAML for a Spring Boot 1.4 application, I have to use the main/resources/application.yaml file. So far, so good.
How can I override these dependencies using YAML depending for a specific profile when running or testing the application.
When using Spring Boot 1.4 (this applies for release 1.3 as well) YAML properties are always defined in the main/resources/application.yaml file. Depending on the chosen profile, the properties can be overridden by another set of properties.
To override these properties for test, a YAML file has to be given in the /test/resources/application-.yaml file, where is replaced by the active profile. It is important to see that the profile always has to be given, even when there is no active profile. In that case, the profile is ‘default’.
To override the properties when running the application, properties can be overridden for a specific profile using in a file called main/resources/application-.yaml file. Even for this situation, if no profile is given, the profile for the filename is ‘default’.
Example
The test class Spring14ApplicationTests.java for Spring Boot 1.4 has the following definition
#RunWith(SpringRunner.class)
#SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class Spring14ApplicationTests {
…
}
For Spring Boot 1.3, the same file has the following definition
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes=SpringDb14Application.class)
#WebAppConfiguration
public class SpringDb14ApplicationTests {
...
}

Resources