Failed to load application.properties file while using #DataJpaTest annotation - spring

I am trying to load application properties in Spring boot project for testing. I am also using #DataJpaTest annotation. Many people suggested to use #TestPropertySource annotation with combination of #datajpaTest but it is not loading properties. It is loading properties if I user #SpringBooTest.
#RunWith(SpringRunner.class)
#DataJpaTest
#TestPropertySource(locations="classpath:application.properties")
public class EntityRepositoryTests {
}
My application properties file is in main/resource/ folder.
It is working if I use #SpringBootTest(properties = { "classpath:application.properties" } but I have
#Autowired
private TestEntityManager entityManager;
which is failing to autoconfigure with SpringBootTest. I have also tried #ContextConfiguration(initializers=ConfigFileApplicationContextInitializer.class) but no luck.

For test you must use
#ActiveProfiles("test")
along with application-test.properties
These are what I just used
#RunWith(SpringRunner.class)
#DataJpaTest(showSql = false)
#AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
#ActiveProfiles("test")

Related

How Do I Manually Wire A Spring Boot Integration Test?

Normally, I would test the web layer in a Spring project like this:
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class SpringBootDemoApplicationTests extends AbstractTestNGSpringContextTests {
#LocalServerPort
int randomServerPort;
#Autowired
private TestRestTemplate restTemplate;
However, I currently have a difficult back end that requires a specific #TestConfiguration class to manually instantiate the test dependencies using beans.
This ultimately means that I can't use the #SpringBootTest annotation as it will try to create conflicting beans and fail to instantiate others.
If I am not using the #SpringBootTest annotation, I can manually create the TestRestTemplate instead of autowiring it, but what do I need to do to start the embedded local server on a random port?
I would still continue using #SpringBootTest, and combine that with using #Profile on your configuration classes.
That way you could have a configuration which is only used during tests, by using #ActiveProfiles on your #SpringBootTest classes. In the same way you can turn other config classes on or off depending on whether you want them to load or not.
For example on your test would have the following
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
#ActiveProfiles("unittest")
public class SpringBootDemoApplicationTests extends AbstractTestNGSpringContextTests {
...
}
Then create a configuration class which will instantiate your components the way you want them in test
#Profile("unittest")
#Configuration
public void TestConfiguration {
...
}
And you can use profiles to stop your other configuration class from loading during tests.
#Profile("!unittest")
#Configuration
public void ProdConfiguration {
...
}

Spring-boot application-test.properties

I am trying to unit test the spring-boot application using junit. I have placed the application-test.properties under src/test/resources. I have a ApplicationConfiguration Class which reads the application.properties.
My test class looks like this
#RunWith(SpringRunner.class)
#SpringBootTest(classes=ApplicationConfiguration.class)
#TestPropertySource(locations = "classpath:application-test.properties")
#ActiveProfiles("test")
public class TestBuilders {
#Autowired
private ApplicationConfiguration properties;
When I try to read the properties, it is always null.
My ApplicationConfiguration Class looks something like this
#Configuration
#ConfigurationProperties
#PropertySources({
#PropertySource("classpath:application.properties"),
#PropertySource(value="file:config.properties", ignoreResourceNotFound =
true)})
public class ApplicationConfiguration{
private xxxxx;
private yyyyy;
I tried all possible ways that I found on google.. No luck. Please help!
Thanks in Advance.
The issue is you don't have #EnableConfigurationProperties on your test class.
When you load the application it start from main class(one which has #SpringBootApplication) where you might have #EnableConfigurationProperties and hence it works when you start the application.
Whereas when you are running the Test with only ApplicationConfiguration class as you have specified here
#SpringBootTest(classes=ApplicationConfiguration.class)
Spring doesn't know that it has to Enable Configuration Properties and hence the fields are not injecting and hence null. But spring is reading your application-test.properties file. This can be confirmed by just injecting the value directly in your test class
#Value("${xxxxx}")
private String xxxxx;
Here the value is injected. But to inject into a class with ConfigurationProperties you need to enable it using #EnableConfigurationProperties
Put #EnableConfigurationProperties on your test class and everythhing works fine.

Spring boot cucumber testing

I try to perform some Cucumber tests of a Spring boot application.
It seems like Spring Boot is not started before tests are running.
What am i missing?
https://bitbucket.org/oakstair/spring-boot-cucumber-example
My Cucumber repo still runs without doing all the above steps:
https://github.com/BarathArivazhagan/Cucumber-spring-integration
Docs : https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html
To add more:
#SpringBootTest takes care of loading the application context in that case #ContextConfiguration is reductant.
Spring test automatically provides a bean of TestRestTemplate which can be autowired but still it should work with RestTemplate also.
It still runs without RANDOM_PORT but RANDOM port can be also used in conjunction for testing.
Let's say you have a feature file, feature1, and glueCode in org.xyz.feature1
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"pretty"},
features = "src/test/java/resources/feature/feature1",
glue = {"org.xyz.feature1"})
public class CucumberTest {
}
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {Application.class},
webEnvironment = WebEnvironment.RANDOM_PORT)
#ContextConfiguration
#Ignore
#Transactional
public class FeatureTest extends CucumberTest {
#LocalServerPort
int randomServerPort;
#Given("........")
public void test_1 {
}
}
I found the problem and has updated the repo.
I did the following to get it working:
Added RANDOM_PORT to #SpringBootTest
Added #ContextConfiguration
Switched from RestTemplate to TestRestTemplate

How to exclude classes that are added using Spring's AutoConfiguration when using #WebMvcTest?

I want to test my Controller using #WebMvcTest and mock the dependencies, but Spring Boot's AutoConfiguration loads my Couchbase (Spring Data) configuration automatically. Couchbase is not available on some platforms which run the test, so the Test class will throw an Exception. How can I exclude some classes from the AutoConfiguration mechanism?
I tried the excludeFilters option of #WebMvcTest and #ActiveProfile to load another Application Context, but that didn't work.
Test configuration:
#RunWith(SpringRunner.class)
#WebMvcTest(value = ExchangeJobImportController.class, excludeFilters = #ComponentScan.Filter(classes = CouchbaseConfiguration.class))
#ActiveProfiles("test")
public class ExchangeJobImportControllerTest {
...
}
Couchbase Configuration:
#Configuration
#EnableCouchbaseAuditing
#EnableConfigurationProperties({CouchbaseProperties.class})
#EnableCouchbaseRepositories(basePackages = "com....")
public class CouchbaseConfiguration extends AbstractCouchbaseConfiguration {
...
}
After some more struggling I found the solution: exclude the #SpringBootApplication annotated class in the #WebMvcTest annotation:
#RunWith(SpringRunner.class)
#WebMvcTest(value = ExchangeJobImportController.class, excludeAutoConfiguration = Application.class, secure = false)
#ActiveProfiles("localhost")
public class ExchangeJobImportControllerTest {
...
}
For the record, I am using Spring Boot 1.5.1.RELEASE
I know it's been some time but I suppose the reason why the #ComponentScan.Filter solution doesn't work is that it looks for an annotation type for the classes field by default.
So, setting the FilterType as ASSIGNABLE_TYPE should work in your case:
#ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = CouchbaseConfiguration.class
)

Spring Boot MockMVC Test does not load Yaml file

I have my configuration in application.yml file in the root of classpath (src/main/resources/). The configuration gets loaded fine when I start the application normally. However in my test the application.yml file gets not loaded at all.
The header of my test looks as follow:
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(classes = Configuration.class)
#org.junit.Ignore
public class ApplicationIntegrationTest {
#Inject
private WebApplicationContext wac;
private MockMvc mockMvc;
#Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
...
The configuration class:
#EnableAutoConfiguration
#ComponentScan("c.e.t.s.web, c.e.t.s.service")
public class Configuration extends WebMvcConfigurerAdapter {
When I debug the application I see that the yml files get loaded in ConfigFileApplicationListener, in the test however the ConfigFileApplicationListener gets not called.
There is a whole chapter in the Spring Boot Reference guide regarding testing. This section explains how to do a basic test for a Spring Boot application.
In short when using Spring Boot and you want to do a test you need to use the # SpringApplicationConfiguration annotation instead of the #ContextConfiguration annotation. The #SpringApplicationConfiguration is a specialized #ContextConfiguration extension which registers/bootstraps some of the Spring Boot magic for test cases as well.
There is a good integration between StringBoot, jUnit and YAML.
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(MainBootApplication.class)
public class MyJUnitTests {
...
}
#Configuration
#EnableConfigurationProperties
#ConfigurationProperties(prefix = "section1")
public class BeanWithPropertiesFromYML {
...
}
For more details please check my comment here: https://stackoverflow.com/a/37270778/3634283

Resources