Spring boot integration test with multiple data sources getting url cannot be null - spring-boot

Currently, I am working on spring boot application, we are connecting mysql as part of the main database and H2 Db(in memory) as part of integration testing. Now we have requirement to add two more databases, I am connecting multiple data source by providing multiple data sources in application.properties
spring.mys.datasource.url=jdbc:mysql://17.27.24.33:3306/my-db
spring.mys.datasource.username=root
spring.mys.datasource.password=1234
spring.mys.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.teradata.datasource.url=jdbc:mysql://17.27.24.33:3306/mydb
spring.teradata.datasource.username=root
spring.teradata.datasource.password=password
spring.teradata.datasource.driver-class-name=com.mysql.jdbc.Driver
and when we are having single data source I am able to connect to HSQL in memory db as part for test application.properties with profile test
spring.jpa.database: HSQL
spring.jpa.hibernate.ddl-auto=create-drop
spring.profiles.active=test
After adding second data source my integration testing got failed with below error. Basically, we need to implement integration test for both data sources. appreciate any help, thanks.
Our code in the integration test
#SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
#ContextConfiguration(classes = { ServiceConfig.class, JWTProtectedWebSecurity.class })
public abstract class BaseIRTest {
}
See the error below while running the maven test
2017-11-22 12:31:04.479 ERROR 14648 --- [ main] o.a.tomcat.jdbc.pool.ConnectionPool : Unable to create initial connections of pool.
java.sql.SQLException: The url cannot be null
at java.sql.DriverManager.getConnection(DriverManager.java:649) ~[na:1.8.0_60]
at java.sql.DriverManager.getConnection(DriverManager.java:208) ~[na:1.8.0_60]
at org.apache.tomcat.jdbc.pool.PooledConnection.connectUsingDriver(PooledConnection.java:308) ~[tomcat-jdbc-8.5.11.jar:na]
at org.apache.tomcat.jdbc.pool.PooledConnection.connect(PooledConnection.java:203) ~[tomcat-jdbc-8.5.11.jar:na]
at org.apache.tomcat.jdbc.pool.ConnectionPool.createConnection(ConnectionPool.java:732) [tomcat-jdbc-8.5.11.jar:na]
at

Related

Unable to externalize Hikari properties with Spring Cloud Config in Client

I have this property file which I store in a GitHub repo:
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.jdbcUrl=*DB URL*
spring.datasource.username=*USERNAME*
spring.datasource.password=*ENCRYPTED PASSWORD*
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.maximum-pool-size=10
My config server pulls up the details from this repo.
Now I have a client that requires these properties to configure the HikariDataSource.
but when I start the client I get the following Error:
***************************
APPLICATION FAILED TO START
***************************
Description:
Cannot determine embedded database url for database type NONE
Action:
If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active).
Seems to me like Hikari is unable to get these properties at start-up.
I was configuring my Hikari DataSource like so in my config class:
#Bean
#ConfigurationProperties("spring.datasource")
public HikariDataSource dataSource() {
return (HikariDataSource) DataSourceBuilder.create().type(HikariDataSource.class).build();
}
After removing this bean I still get the same error.
Any idea about what I should be doing here?
Thanks.
I was able to fix this by adding #EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class}) to the main class.

Why does my Oracle DataSource have a replay error only when unit testing?

My Spring Boot 1.5.17 (Spring 4.3.20) server works fine with bootRun or when deployed.
However, I have an Oracle DataSource that fails only when unit-testing:
java.lang.AssertionError: Server is sending a non-null replay context
but our replayModes=[]
A Google Search for this error doesn't have exact results.
I am able to unit-test with a different Oracle database.
I get the error with a full Application testing context
#RunWith(SpringRunner.class)
#SpringBootTest(
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { TestingUserConfiguration.class, Application.class }
)
As well as just the single DataSource config and Service
#RunWith(SpringRunner.class)
#SpringBootTest(classes = {
MyDbConfig.class,
MyService.class
})
Both oracle.jdbc.pool.OracleDataSource and oracle.jdbc.replay.OracleConnectionPoolDataSourceImpl have the error.
UCP makes no difference.
OracleConnectionPoolDataSourceImpl has a different error:
java.sql.SQLException: Unsupported feature
Tried upgrading from OJDBC 12.2 to 2018.3, no difference.
Has anyone seen this error before?
Any ideas on why it only appears with Spring unit tests?
After much head scratching, I found that doing this in the test suite:
static {
ClassLoader.getSystemClassLoader().setPackageAssertionStatus("oracle.jdbc.driver", false);
}
Solved My issue, I am sure this is a bug in the oracle.jdbc.driver.T4CTTIfun class
You can add "-da:oracle..." to your JAVA_TOOL_OPTIONS to turn off oracle asserts. To get around this.
Trent

SpringBoot 1.5 : #SpringBootTest and memory Database

I have a SpringBoot application with spring data/jpa to connect for database.
And a propertie file yml where defined the database connection.
Everything works very well.
I create a test like that :
#ActiveProfiles("dev")
#RunWith(SpringRunner.class)
#SpringBootTest(classes = MyMicroServiceApp.class, webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT)
public class MyMicroServiceAppTest {
#Test
public <T> void postConnex() {
//Create Object connexCreate
...
// Create POST
ResponseEntity<Udsaconnex> result1 = this.restTemplate().postForEntity("http://localhost:" + port + "/v1/connex",
connexCreate, Udsaconnex.class);
id = result1.getBody().getIdconnex();
assertEquals(result1.getBody().toString().isEmpty(), false);
}
}
For my test, i have not configured properties for database connection but the test work and i view in console that :
Hibernate: drop table connex if exists
I don't understand why, #SpringBootTest mock database like #DataJpaTest automatically ??
It's possible but i don't find anything about that in spring boot documentation.
Thanks for your help.
If you have application.yml file specifying DB location, then SpringBootTest will obviously use the same configuration and will use your configured DB.
From the title of your question I guess you have an in-memory database in your build dependencies. Spring-boot has some autoconfiguration for certain database (H2, HSQL, Derby) if they are found on the classpath. See this link for a list of the supported databases:
Spring Boot Embedded Database Support

How to mock Eureka when doing Integration Tests in Spring?

I am running a simple Junit Testing a Controller in Spring Boot. The test code looks like this:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {FrontControllerApplication.class})
#WebAppConfiguration
#ComponentScan
#IntegrationTest({"server.port:0", "eureka.client.registerWithEureka:false", "eureka.client.fetchRegistry:false"})
#ActiveProfiles("integrationTest")
public class MyControllerIT {
In the application-integrationTest.properties I have the following Eureka Settings:
####### Eureka
eureka.serviceUrl.default=http://localhost:8767/eureka/
eureka.printDeltaFullDiff=false
eureka.client.refresh.interval=1
eureka.appinfo.replicate.interval=1
eureka.serviceUrlPollIntervalMs=1000
eureka.name=${spring.application.name}
####### Netflix Eureka #######
eureka.client.serviceUrl.defaultZone=http://localhost:8767/eureka/
eureka.client.instanceInfoReplicationIntervalSeconds=1
eureka.client.initialInstanceInfoReplicationIntervalSeconds=0
eureka.instance.virtualHostName=${spring.application.name}
eureka.instance.preferIpAddress=true
eureka.instance.initialStatus=DOWN
eureka.instance.leaseRenewalIntervalInSeconds=3
eureka.instance.leaseExpirationDurationInSeconds=10
eureka.instance.metadataMap.instanceId=${spring.application.name}:${spring.application.instance_id:${random.value}}
eureka.eurekaserver.connectionIdleTimeoutInSeconds=5
eureka.responseCacheAutoExpirationInSeconds=5
when a junit test started I see the following:
2015-09-16 16:46:03,905 ERROR localhost-startStop-1 com.netflix.discovery.DiscoveryClient Can't get a response from http://localhost:8767/eureka/apps/
Can't contact any eureka nodes - possibly a security group issue?
com.sun.jersey.api.client.ClientHandlerException: java.net.ConnectException: Connection refused: connect
at com.sun.jersey.client.apache4.ApacheHttpClient4Handler.handle(ApacheHttpClient4Handler.java:184) ~[jersey-apache-client4-1.11.jar:1.11]
The test passes, that is not the problem, but I see a lot of exception stack traces that has to do with Eureka. The questions is if there is a way to mock eureka or another way to skip brining it up when doing tests?
The benefit would be easier to see relevant stack traces if test would fail and tst would run much faster
Another solution is to disable the Eureka Client in your application.properties or application.yml file under test/resources
applications.properties:
eureka.client.enabled=false
application.yml:
eureka:
client:
enabled: false
This has the benefit of not needing to remeber to include the system property for every JUnit test that requires disabling the Eureka Client.
You can set a system property for eureka.client.enabled=false for tests.
If you're running the tests using gradle you can do this:
tasks.withType(Test) {
systemProperty 'eureka.client.enabled', 'false'
}
If you're running tests in an IDE then you'll have to set the system property there as well.

IllegalTransactionStateException when running in Jetty

I have a WAR application as follows:
JPA/Hibernate 4.1.9.Final
Hibernate Envers 4.1.9.Final
Spring 3.1.3.RELEASE
Spring MVC with JSON/REST
My frontend (web page) makes a request, this leads to a new entity to be saved (this seems to succeed in any case) and then Envers will save corresponding revision info.
Typical deployment is in Tomcat 7, where this works just fine.
For unit testing I spin up a Jetty (8.1.9.v20130131) programmatically, which fails. It baffles me why this behavior is different. I can only imagine that Jetty has a different (lesser standard, perhaps) transaction management on board than Tomcat, but I've failed to pin it down or otherwise work around this.
Below is how I create the web application programmatically:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"classpath:applicationContext.xml" })
public class AddCustomerTest {
And:
server = new Server(serverPort);
WebAppContext webAppContext = new WebAppContext();
webAppContext.setContextPath("/webapp");
webAppContext.setWar("src/main/webapp");
webAppContext.setServer(server);
server.setHandler(webAppContext);
Below is the essential exception that I'm getting:
Caused by: org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:357)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:334)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at com.sun.proxy.$Proxy115.getByUuid(Unknown Source)
at com.totaalsoftware.incidentmanager.entity.audit.RevisionEntityListener.setUser(RevisionEntityListener.java:53)
at com.totaalsoftware.incidentmanager.entity.audit.RevisionEntityListener.instanceNewRevision(RevisionEntityListener.java:40)
at com.totaalsoftware.incidentmanager.entity.audit.RevisionEntityListener.newRevision(RevisionEntityListener.java:34)
at org.hibernate.envers.revisioninfo.DefaultRevisionInfoGenerator.generate(DefaultRevisionInfoGenerator.java:95)
at org.hibernate.envers.synchronization.AuditProcess.getCurrentRevisionData(AuditProcess.java:124)
at org.hibernate.envers.synchronization.AuditProcess.executeInSession(AuditProcess.java:106)
at org.hibernate.envers.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:155)
at org.hibernate.engine.spi.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:662)
... 80 more
My RevisionEntityListener looks up some user data (from the database, using Hibernate of course). Clearly there's no transaction available, but only when running in Jetty. I've tried marking the RevisionEntityListener transactional in various ways, to no avail.
Let me know if you need any other info. Your help much appreciated!
Stupid me...
The following two lines were copied over from some other test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({"classpath:applicationContext.xml" })
These two lines served no purpose since the entire application was loaded through the instantiation and configuration of Jetty. But somehow the above clashed with the application in the Jetty server, probably due to being in the same JVM. Removing the above two lines from the test class fixed it!

Resources