Spring Test : why cannot access application.properties? - spring-boot

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

Related

How to make spring boot test app independent of external property source?

I am writing a controller test for a spring boot application. To use the spring application context I am using SpringRunner class. The problem is the main application class has a property source defined to a specific file path.
When I am running the test I am getting a FileNotFound exception from the hardcoded file. I want my test to be independent of this property source.
I cannot add the 'ignoreResourceNotFound' option for property source in the main application.
Below is the main application class with property source defined.
#SpringBootApplication
#PropertySource("file:/opt/system/conf/smto/management.properties")
#EnableConfigurationProperties
public class ManagementApp {
public static void main(String[] args) {
SpringApplication.run(ManagementApp.class, args);
}
}
I am also adding my test class below
#RunWith(SpringRunner.class)
#TestPropertySource(locations = {"classpath:application.properties","classpath:management.properties"})
#DirtiesContext
#EmbeddedKafka(topics = {"management-dev"},partitions = 1,
controlledShutdown = false,brokerProperties = {"listeners=PLAINTEXT://localhost:9092", "port=9092"})
#AutoConfigureMockMvc
#WebMvcTest(Controller.class)
public class ControllerTest {
}
I have found a workaround to create the spring context in this scenario. I have changed my testing class package and because of it, the spring-boot test cannot find the primary configuration class. And then provided all the required packages to create the application context.
Reference for this solution found from spring docs here.
Spring Boot’s #*Test annotations will search for your primary configuration automatically whenever you don’t explicitly define one.
The search algorithm works up from the package that contains the test until it finds a #SpringBootApplication or #SpringBootConfiguration annotated class. As long as you’ve structured your code in a sensible way your main configuration is usually found.

Spring boot - test properties overriden with prod properties

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.

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.

How to correctly using Spring profile on windows

I am trying to maintain different Spring profiles for development and production, for which I have created a folder(web skeleton) on my desktop with my Spring Boot project, application-dev.properties and application-prod.properties.
However, I am unable to import the profile into my project. The code that I use to import it to my project is as follows.
#Configuration
#Profile("dev")
#PropertySource("file:///${user.home}/web skeleton/application-dev.properties")
public class DevelopmentConfig {
#Bean
public EmailService emailService(){
return new MockEmailService();
}
Can someone tell me if this is the right way to use PropertySource in Spring.
You can optionally define a custom source where we’re storing these properties, else the default location (classpath:application.properties) is looked up. So we now add the above annotations to the existing properties class:
#Configuration
#PropertySource("classpath:configprops.properties")
#ConfigurationProperties(prefix = "dev")
public class ConfigProperties {
// previous code
}
Now any properties defined in the property file that has the prefix dev and the same name as one of the properties are automatically assigned to this object.
#Simple properties
dev.host=mailer#mail.com
dev.port=9000
Check this
I have done this kind of configuration too
Just add below code in your configuration class
#PropertySource("classpath:application-${spring.profiles.active}.properties")
And this propery in application.properties
spring.profiles.active=dev
you can change it to prod and cert as per you need.

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

Resources