14
votes

Updated Question based upon feedback:

I have a spring-boot application that has three databases: H2 for integration testing, and Postgresql for qa & production. Since spring-boot creates a default datasource for you, I don't have anything defined for my integration tests. I thought I would use application.properties to define my datasource connection values but I am not certain what is the best way to handle this.

I have two files:

src/main/resources/application.properties

spring.profiles.active=production
appName = myProduct
serverPort=9001

spring.datasource.url=jdbc:postgresql://localhost/myDatabase
spring.datasource.username=user
spring.datasource.password=password
spring.datasource.driverClassName=org.postgresql.Driver

spring.jpa.hibernate.hbm2ddl.auto=update
spring.jpa.hibernate.ejb.naming_strategy=org.hibernate.cfg.EJB3NamingStrategy
spring.jpa.hibernate.show_sql=true
spring.jpa.hibernate.format_sql=true
spring.jpa.hibernate.use_sql_comments=false
spring.jpa.hibernate.type=all
spring.jpa.hibernate.disableConnectionTracking=true
spring.jpa.hibernate.default_schema=dental

src/main/resources/application-test.properties

spring.profiles.active=test
serverPort=9002

spring.datasource.url = jdbc:h2:~/testdb
spring.datasource.username = sa
spring.datasource.password = 
spring.datasource.driverClassName = org.h2.Driver

liquibase.changeLog=classpath:/db/changelog/db.changelog-master.sql

I used to run my tests with with gradle (using "gradle build test") or within IntelliJ. I updated my gradle file to use:

task setTestEnv {
    run { systemProperty "spring.profiles.active", "test" }
}

But when I run gradle clean build setTestEnv test I get errors that seem to indicate the test is trying to connect to an actual Postgresql database:

Caused by: org.postgresql.util.PSQLException: Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.
    at org.postgresql.core.v3.ConnectionFactoryImpl.openConnectionImpl(ConnectionFactoryImpl.java:138)
    at org.postgresql.core.ConnectionFactory.openConnection(ConnectionFactory.java:66)
    at org.postgresql.jdbc2.AbstractJdbc2Connection.<init>(AbstractJdbc2Connection.java:125)
    at org.postgresql.jdbc3.AbstractJdbc3Connection.<init>(AbstractJdbc3Connection.java:30)
    at org.postgresql.jdbc3g.AbstractJdbc3gConnection.<init>(AbstractJdbc3gConnection.java:22)
    at org.postgresql.jdbc4.AbstractJdbc4Connection.<init>(AbstractJdbc4Connection.java:32)
    at org.postgresql.jdbc4.Jdbc4Connection.<init>(Jdbc4Connection.java:24)
    at org.postgresql.Driver.makeConnection(Driver.java:393)
    at org.postgresql.Driver.connect(Driver.java:267)
    at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:278)
    at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:182)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:701)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:635)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.init(ConnectionPool.java:486)
    at org.apache.tomcat.jdbc.pool.ConnectionPool.<init>(ConnectionPool.java:144)
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.pCreatePool(DataSourceProxy.java:116)
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.createPool(DataSourceProxy.java:103)
    at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:127)
    at liquibase.integration.spring.SpringLiquibase.afterPropertiesSet(SpringLiquibase.java:288)
    ... 42 more
Caused by: java.net.ConnectException: Connection refused
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)

I haven't figured out how to set the default system.property == "test" within IntelliJ yet...

2
Why aren't you letting Spring Boot configure your datasource. Simply put the production one in the application.properties then for your tests create an application-test.properties file containing the settings for your test database. (Which will override the main ones). Or if you only run your tests from maven/gradle then simply add an application.properties to src/test/resources overriding the main application.properties.M. Deinum
OK, so if I have a src/main/resources/application.properties (with all settings, including production db) and a src/main/resources/application-test.properties (with just the H2 db settings). When I run my tests (either from command line or inside IntelliJ) then I just need to pass in a variable indicating "test" such as --profile=test? Then when I run my app, the application.properties will be used.sonoerin
You shouldn't need to configure the datasources yourself, remove them and only configure the spring.datasource.* properties in the application.properties file of your choice. Spring Boot will take care of constructing the datasource.M. Deinum
I updated the question to show my current statussonoerin
The fact thatyou use db.* as a property seems to me you are configurating the datasource yourself. As mentioned remove your datasource and just use the appropriate spring.datasource.* properties this will let Spring Boot create the datasource. Make sure that you override all properties (password should probably be empty for H2).M. Deinum

2 Answers

17
votes

See section 21.3 of the Spring Boot documentation. This section describes how to define profile specific property files that use the format application-{profile}.properties. This can help you isolate properties on a per profile basis.

10
votes

You can annotate your tests adding @ActiveProfiles in the following way:

@SpringApplicationConfiguration(classes = {Application.class, TestSpringConfiguration.class})
@Test(groups = "integration")
@ActiveProfiles("test")
public class MyServiceTest extends AbstractTransactionalTestNGSpringContextTests {
...
   @Test 
   public void testSomething() {
      ...
   }
} 

I'm using TestNG but JUnint wouldn't be much different. You can also specify additional configuration as showed in the example above.

That way you won't need to set the profile in build.gradle or launch configuration in IntelliJ