Second datasource in spring application.properties

2019-09-06 17:51发布

问题:

I have datasource defined in my application.properties as Oracle database and that's ok, the controller & repository work fine, I can persist entities and fetch database records.

I have integration tests written. Before I connected my app with database I created some objects and persisted them in @PostConstruct method - and that was ok. But now, when I connected everything with database, my tests try to fetch records from the table which is pretty large. I think that's due to my application.properties file in which defined datasource is Oracle database.

spring.datasource.driverClassName=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@blabla
spring.datasource.username=blabla
spring.datasource.password=blabla
spring.jpa.hibernate.ddl-auto=none
spring.jpa.generate-ddl=false

I want to carry on tests using some in-memory HSQL, not real database. But I still want my controller and repository to use the real one. How can I do it? Is there any possibility to add second datasource in application.properties? Or maybe an easier solution?

回答1:

In Spring 4 you have @Profile annotation so you can use its advantage. Create another like application-test.properties file with it's own properties.

Create configuration for your tests:

@Configuration
@Profile("test") 
public class TestConfiguration {
    ....
}

Then annotate your class with @ActiveProfiles annotation:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = TestConfiguration.class)
@ActiveProfiles("test")
public class TestRepository {
   ...
}


回答2:

There are many ways to achieve this, one way is to use Spring profiles. The test profile would use a different properties file than the production one.



回答3:

Spring has org.springframework.mock.jndi.SimpleNamingContextBuilder package that allows you to bind the dataSource programatically.

Sample Test class that I use:

public class MockJNDIContext {

    @BeforeClass
    public static void setUpClass() throws Exception {

        SimpleNamingContextBuilder builder = SimpleNamingContextBuilder.emptyActivatedContextBuilder();
        OracleConnectionPoolDataSource ds = new OracleConnectionPoolDataSource();//Use your own Connection Pool DS here as you require
        ds.setURL("jdbc:oracle:thin:@10.xxx.xxx.xx:9999:SID");
        ds.setUser("USER");
        ds.setPassword("PASSWORD");
        //Bind it to the JNDI you need
        builder.bind("java:comp/env/jdbc/MY/APP", ds);

    }

    @Test
    public void test(){
        System.out.println("JNDI Initialized");
    }

}

Suite Class:

@RunWith(Suite.class)
@Suite.SuiteClasses({
        MockJNDIContext.class,
        InitializeTestConfig.class
})
public class ServiceSuite{
}

May be this helps? If you are trying to load from one more application.props, use one more class (InitializeTestConfig.class) that initializes and passes the DS args and add to suite as mentioned above and try?