SpringBoot jUnit is not loading application-dev.xml - java

I am using SpringBoot for latest development.Profile based configuration we have so there are 3 files are there
application-{env}.properties, env means dev,stage and prod
When I run the project locally in eclipse using -Dspring.profiles.active=dev run configuration it is picking configurations from application-dev.properties. But If I try to run a jUnit, it is expecting application.properties otherwise throwing error.I put a application.properties it is working fine.Please tell me how to configure JUnit with profile based so that which will pick application-dev.properties.Please give your input on this, thanks in advance.
#SpringBootTest
#RunWith(SpringRunner.class)
public class ProcessingServiceTest {
#Test
public void testlet2MeIn() throws Exception{
}
}

Did you try setProperty ?
#SpringBootTest
#RunWith(SpringRunner.class)
public class ProcessingServiceTest {
public ProcessingServiceTest(){
System.setProperty("spring.profiles.active","dev");
}
#Test
public void testlet2MeIn() throws Exception{
}
}

you can specify the properties files using #TestPropertySourceand specify which file should be used to load properties for tests
#TestPropertySource(locations = "classpath:application-dev.properties")
Or
the simplest way is to use this on your test class #ActiveProfiles("dev")

Related

Data Jpa Test fails to load properties

I am using Hashi Corp vault in Spring Boot project. I am able to run the project without any issue. But when I run unit tests, secret-id and role-id are not being passed. I tried the following but got an exception saying both are empty. Tried hard coding the values, that didn't work either
EmployeeTest.java
#RunWith(SpringRunner.class)
#DataJpaTest
#ActiveProfiles(value = "ide")
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class EmployeeTest
{
private final Logger logger= LoggerFactory.getLogger(getClass());
#Autowired
EmployeeRepository employeeRepository;
#Test
public void getEmployeeById()
{
Employee employee=employeeRepository.getOne(13L);
logger.info(employee.toString());
}
}
Update:
I am able to pass secret-id and role-id through VM arguments but still properties are not resolving
Okay, it turns out when using profile from src/main/resources/application-ide.yml in spring boot test, properties are not being replaced by vault vaules. Copying the same file to src/test/resources/application-ide.yml fixes the issue.
TL;DR
For Spring Boot testing always better to use properties file from src/test/resources rather than src/main/resources

How to manage maven profiles through annotations/pom.xml?

Ref - Maven Profiles
I don't want to specify profile through command line arguments while running. Because, if I change it locally, then changes have to be made thoughout CI stream.
Scenario:
There are basically two profiles "PROD" and "TEST". I have annotated methods using these. Basically, I connect different databases under different profiles.
While the test classes are annotated with #ActiveProfile("TEST")
I run tests using mvn clean test-compile failsafe:integraton-test and run application using mvn springboot:run
Problem:
Case 1:
Issue: Only PROD related methods run for PROD and TEST.
If I don't use #Profile("PROD") and only use #Profile("TEST") and I use #ActiveProfiles("TEST") as specified in reference. Both mvn commands without any flag specified above only use the beans which are not annotated with profiles.
Case 2:
Issue: PROD doesn't run.
If I use both PROD and TEST without any flag, mvn clean test-compile failsafe:integraton-test command runs perfectly (only when #ActiveProfile("TEST") is specified otherwise I'd have to send a flag -Dspring.profiles.active=TEST) but springboot:run doesn't work as it cannot pick up any database configuration and no active profile found.
This is the case even when I Annotate PROD profiles with both PROD and #Primary
Surprisingly even If I provide command line argument the result is the same. mvn springboot:run -Dspring.profiles.active=PROD
If I annotate the main class where these profiles are run with #ActiveProfiles("PROD"), the result is the same.
Ideal Scenario/Expected:
To run tests using mvn test-compile failsafe:integration-test preferably without flag. (Already acheived but prod isn't working)
To run prod using mvn springboot:run emphasis of no flags.
Preferable changes:
Java annotations: Annotations such as #Profile, #ActiveProfile, #Primary which tells Spring-boot or maven what to use.
POM.xml: setting profiles for directing maven what to use.
in short i think you just need to add spring.profiles.active=PROD to your application.properties
I put together an example which prints the contents of a bean which differs between prod ant test, hope this helps.
When running the below code i get the following output:
mvn spring-boot:run: The String in the context is: PROD
mvn clean test: The String in the context is: TEST
ProfilesApplication.java:
#SpringBootApplication
public class ProfilesApplication implements CommandLineRunner {
Logger logger = LoggerFactory.getLogger(ProfilesApplication.class);
#Autowired
private String profiledString;
public static void main(String[] args) {
SpringApplication.run(ProfilesApplication.class, args);
}
#Bean
#Profile("PROD")
public String prodString() {
return new String("PROD");
}
#Bean
#Profile("TEST")
public String testString() {
return new String("TEST");
}
#Override
public void run(String... args) throws Exception {
logger.info("The String in the context is: {}", profiledString);
}
}
application.properties:
spring.profiles.active=PROD
ProfilesApplicationTests.java:
#RunWith(SpringRunner.class)
#SpringBootTest
#ActiveProfiles("TEST")
public class ProfilesApplicationTests {
#Test
public void contextLoads() {
}
}

Create Spring Boot test with separate application.properties

I am developing web app with Spring Boot, and now I am trying to create tests for DAO layer, and I'd like to use different configurations, which will read custom property file instead of standard one. But Iam having trouble with that, it always reads default application. and hibernate.properties.
The want to do it in order to have different hibernate.ddl-auto properties for test. But when I run the test, I see that Spring reads properties from the hibernate.properties which is in resource folder (I've purposely made a typo in that file in order to get exception if it was read by Spring). But why does it read that file even when I use #TestPropertySource? I see there's something that I don`t know about that, but what?
package src/test/java/com.guard/dao
#RunWith(SpringRunner.class)
#DataJpaTest
#Rollback
public class LifeguardDaoTest {
#Autowired
private LifeguardDao lgDao;
#Test
public void selectTest(){
for (Lifeguard lg :lgDao.getAll()) {
System.out.println(lg);
}
}
}`
Test configuration class is to setup context
package src/test/java/com.guard
#SpringBootApplication
#EntityScan(value = {"com.guard.dao","com.guard.model"})
#TestPropertySource(value = {"classpath:application-test.properties", "classpath:hibernate-test.properties"})
public class TestConfiguration {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(TestConfiguration.class, args);
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
System.out.println("Spring boot test generated " + beanNames.length + " beans");
}
}
Required application-test.properties and hibernate-test.properties are on src/test/java path
Here's project structure (don`t know how to design it here, sorry)
|src
|--main
|----java
|------com.guard
|----------configuration
|-------------GuardApplication.class (#SpringBootApplication,requires default props)
|--test
|----java
|------application-test.properties
|-------hibernate-test.properties
|-----com.guard
|-------TestConfiguration.class
|-------dao
|---------LifeguardDaoTest.class
My application-test.properties
`
spring.jpa.properties.hibernate.use_sql_comments=true
spring.jpa.hibernate.dialect=org.hibernate.dialect.HSQLDialect
spring.jpa.hibernate.show_sql=false
spring.jpa.hibernate.format_sql=true
spring.jpa.hibernate.hbm2ddl-auto=create
# even in case if it won`t use "spring.jpa" prefix
hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.show_sql=true
hibernate.format_sql=true
`
Create new resources directory inside test directory and put your test properties file there. Also rename your properties files to application.properties and hibernate.properties
Spring tests will take properties from test/resources/ directory. And in this approach, you do not need #TestPropertySource
Typically, #TestPropertySource is used in conjunction with #ContextConfiguration.
Try with this configuration class.
#Configuration
#ComponentScan
#Profile("test")
public class TestConfiguration {
}
And annotation:
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
#ContextConfiguration(classes = TestConfiguration.class)
#ActiveProfiles("test")
#TestPropertySource(locations="classpath:application-test.properties")
public #interface IntegrationTest { }
Then you just write test like this:
#RunWith(SpringJUnit4ClassRunner.class)
#IntegrationTest
public class SomeDaoTest {
...
}

Spring Boot integration tests doesn't read properties files

I would like to create integration test in which Spring Boot will read a value from .properties file using #Value annotation.
But every time I'm running test my assertion fails because Spring is unable to read the value:
org.junit.ComparisonFailure:
Expected :works!
Actual :${test}
My test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {WebTests.ConfigurationClass.class, WebTests.ClassToTest.class})
public class WebTests {
#Configuration
#ActiveProfiles("test")
static class ConfigurationClass {}
#Component
static class ClassToTest{
#Value("${test}")
private String test;
}
#Autowired
private ClassToTest config;
#Test
public void testTransferService() {
Assert.assertEquals(config.test, "works!");
}
}
application-test.properties under src/main/resource package contains:
test=works!
What can be the reason of that behavior and how can I fix it?
Any help highly appreciated.
You should load the application-test.properties using #PropertySource or #TestPropertySource
#RunWith(SpringJUnit4ClassRunner.class)
#TestPropertySource(locations="classpath:application-test.properties")
#ContextConfiguration(classes = {WebTests.ConfigurationClass.class, WebTests.ClassToTest.class})
public class WebTests {
}
for more info: Look into this Override default Spring-Boot application.properties settings in Junit Test
Besides the above marked correct answer, there is another nature way to load application-test.properties: Set your test run "profile" to "test".
Mark your test cases with:
#ActiveProfiles("test")
#RunWith(SpringJUnit4ClassRunner.class)
application-xxxx.properties is a naming convention for properties of different "profile".
This file application-xxxx.properties should be placed in src/main/resources folder.
"Profile" is also useful in bean configuration.

Specify config file for #SpringApplicationConfiguration

Currently my integration test look like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = PingFacadeApplication.class)
#WebIntegrationTest
public class PingResourceTest {
// some tests that use RestTemplate to contact PingFacadeApplication
}
PingFacadeApplication is defined like this:
#SpringBootApplication
#EnableDiscoveryClient
#ComponentScan(basePackages = "edu.self.myapp.ping")
public class PingFacadeApplication {
public static void main(String[] args) {
System.setProperty("spring.config.name", "ping-facade-server");
SpringApplication.run(PingFacadeApplication.class, args);
}
}
When normally starting (i.e. running the jar) PingFacadeApplication, the config file (ping-facade-server.yml) is correctly read from src/main/resources. However, when running my integration tests, the config files appears to never be read because the server is always started on port 8080. I've also tried to put the config file in src/test/resources but no luck.
I know I can change the port in the WebIntegrationTest annotation but I'd like to avoid having it in two places.
Thanks a lot.
A solution is to indicate the name of the configuration file with the #WebIntegrationTest annotation:
// ...
#WebIntegrationTest("spring.config.name=ping-facade-server")
public class PingResourceTest {
In my case I have a ping-facade-server.yml file in src/test/resources.

Categories

Resources