Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring boot not resolving custom properties from application.properties during integration tests

My Spring Boot test configuration is as follows:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {TestEnd2EndIntegrationConfiguration.class})
@WebAppConfiguration
@ActiveProfiles(Profiles.TEST)//=="test"
@Transactional
public abstract class AbstractEnd2EndIntegrationTest {

}

Then from application-test.properties I have the following custom properties:

database.hibernate.dialect=org.hibernate.dialect.H2Dialect
database.hibernate.hbm2ddl.auto=create
database.hibernate.logSqlInfo=true

Which I use as follows:

@Value("${database.hibernate.dialect}")
private String hibernateDialect;

However, the custom properties are not resolved and I get exceptions such as:

com.bignibou.it.controller.signup.SignupRestControllerTest > shouldRejectUnavailableEmailAddress FAILED
    java.lang.IllegalStateException
        Caused by: org.springframework.beans.factory.BeanCreationException
            Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException

edit:

Here is my gradle configuration:

 sourceSets {

        main {
            output.resourcesDir = output.classesDir
        }

        integrationTest {
            java.srcDirs = ['src/it/java']
            resources.srcDirs = ['src/it/resources', 'src/main/resources']
            compileClasspath = sourceSets.main.output + configurations.testRuntime
            runtimeClasspath = output + compileClasspath
        }
    }

   task integrationTest(type: Test) {
        description "Run the integration tests."
        testClassesDir = sourceSets.integrationTest.output.classesDir
        classpath = sourceSets.integrationTest.runtimeClasspath
        reports.html.destination = file("$reports.html.destination/integration")
        reports.junitXml.destination = file("$reports.junitXml.destination/integration")
    }

edit 2:

When I run the tests from the IDE (intellij), I get a different error:

ava:342)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:273)
    at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:103)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 36 more

java.lang.IllegalStateException: Failed to load ApplicationContext
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
    at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
    at org.springframework.test.context.web.ServletTestExecutionListener.setUpRequestContextIfNecessary(ServletTestExecutionListener.java:183)
    at org.springframework.test.context.web.ServletTestExecutionListener.prepareTestInstance(ServletTestExecutionListener.java:123)
    at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:228)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:217)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:276)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:278)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:236)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:87)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
    at org.junit.runners.Suite.runChild(Suite.java:128)
    at org.junit.runners.Suite.runChild(Suite.java:27)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Caused by: java.lang.ClassCastException: org.springframework.boot.context.config.ConfigFileApplicationListener$ConfigurationPropertySources cannot be cast to org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor$ConfigurationPropertySources
    at org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor$ConfigurationPropertySources.finishAndRelocate(ConfigFileEnvironmentPostProcessor.java:528)
    at org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor$PropertySourceOrderingPostProcessor.reorderSources(ConfigFileEnvironmentPostProcessor.java:239)
    at org.springframework.boot.context.config.ConfigFileEnvironmentPostProcessor$PropertySourceOrderingPostProcessor.postProcessBeanFactory(ConfigFileEnvironmentPostProcessor.java:235)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:284)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:131)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:673)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:519)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:667)
    at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:342)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:273)
    at org.springframework.boot.test.SpringApplicationContextLoader.loadContext(SpringApplicationContextLoader.java:103)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98)
    at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116)
    ... 36 more

edit 3:

Here is the detailed cause from the Gradle integrationTest

Caused by: org.hibernate.boot.registry.selector.spi.StrategySelectionException: Unable to resolve name [${database.hibernate.ejb.naming_strategy}] as strategy [org.hibernate.cfg.NamingStrategy]
    at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.selectStrategyImplementor(StrategySelectorImpl.java:128)
    at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveDefaultableStrategy(StrategySelectorImpl.java:155)
    at org.hibernate.boot.registry.selector.internal.StrategySelectorImpl.resolveStrategy(StrategySelectorImpl.java:136)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.processProperties(EntityManagerFactoryBuilderImpl.java:925)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:840)
    at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:152)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:343)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)

edit 4: from a debug within: EntityManagerFactoryBuilderImpl:

configurationValues = {HashMap@4101}  size = 14
 0 = {HashMap$Node@4092} "hibernate.format_sql" -> "${database.hibernate.logSqlInfo}"
 1 = {HashMap$Node@4096} "hibernate.use_sql_comments" -> "${database.hibernate.logSqlInfo}"
 2 = {HashMap$Node@4107} "javax.persistence.nonJtaDataSource" -> 
 3 = {HashMap$Node@4108} "hibernate.hbm2ddl.auto" -> "${database.hibernate.hbm2ddl.auto}"
 4 = {HashMap$Node@4109} "javax.persistence.sharedCache.mode" -> "ENABLE_SELECTIVE"
 5 = {HashMap$Node@4110} "hibernate.dialect" -> "${database.hibernate.dialect}"
 6 = {HashMap$Node@4111} "hibernate.ejb.naming_strategy" -> "${database.hibernate.ejb.naming_strategy}"
 7 = {HashMap$Node@4112} "hibernate.cache.use_second_level_cache" -> "${database.hibernate.cache.use_second_level_cache}"
 8 = {HashMap$Node@4113} "hibernate.ejb.persistenceUnitName" -> "default"
 9 = {HashMap$Node@4114} "hibernate.connection.charSet" -> "${database.hibernate.connection.charSet}"
 10 = {HashMap$Node@4115} "hibernate.show_sql" -> "${database.hibernate.logSqlInfo}"
 11 = {HashMap$Node@4116} "hibernate.cache.region.factory_class" -> "org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"
 12 = {HashMap$Node@4117} "hibernate.generate_statistics" -> "${database.hibernate.generate_statistics}"
 13 = {HashMap$Node@4118} "javax.persistence.validation.mode" -> "AUTO"

One can see that the properties are not expanded... Why is that?

like image 667
balteo Avatar asked Sep 22 '15 14:09

balteo


People also ask

How do I override application properties in Spring boot?

To override your Spring Boot application properties when it's running on Kubernetes, just set environment variables on the container. To set an environment variable on a container, first, initialise a ConfigMap containing the environment variables that you want to override.

Does Spring boot support application properties support?

Spring Boot binds external properties from application. properties (or . yml ) (and other places) into an application at runtime. There is not (and technically cannot be) an exhaustive list of all supported properties in a single location because contributions can come from additional jar files on your classpath.

How does Spring Boot read properties file in test class?

You can use @TestPropertySource annotation in your test class. Just annotate @TestPropertySource("classpath:config/mailing. properties") on your test class. You should be able to read out the property for example with the @Value annotation.

Where does Spring boot look for property file in test?

properties which is located in the project's src/main/resources/ directory. When initializing a project, the default property file is blank. This sample file contains values for the username of a datasource and the root logging level of the application.


1 Answers

You need 3 things to get your properties to be autowired in your integration test classes:

  1. The PropertySource annotation. It looks like you're missing that. You can add something like this to your Abstract Integration Test class:
@PropertySource(value= {"classpath:*.properties"})
  1. The property file must be in your classpath. I recommend adding a separate folder for test and integration test properties. Create an integration-test-resources directory within src/main and copy your property files into there, then configure your build manager to add them as classpath resources.

Here's an example how to do that in Gradle:

sourceSets {
  integrationTest {
     resources {
       srcDir "integration-test-resources"
     }
  }
}
  1. Annotate your property with @Value. Looks like you are already doing this.
like image 82
cosbor11 Avatar answered Oct 07 '22 23:10

cosbor11