6
votes

We have a custom data source that extends BasicDataSource. We have overridden the getConnection method which does a couple things inside of it. When we run the webapp outside of testing, when we call a service from a controller it will grab a new connection and use that connection until the service is done. All is well. However, inside an integration test, the connection appears to be grabbed before the test even calls the controller. Flow below

Regular Run: call controller -> controller calls service method -> connection is grabbed -> service method is run and returns to controller

Integration Test: connection is grabbed -> call controller from test -> controller calls service method -> service method is run and returns to controller

Needless to say, this is giving us problems as having the correct connection is very important for our app. Thoughts?

Edit: Still getting significant issues with this. We've reached a point where we have to avoid creating integration tests, or do some manual connection switching (which defeats half the point of the tests)

DataSource.groovy

dataSource {
pooled = true
dialect="org.hibernate.dialect.OracleDialect"
properties {
    maxActive = 50
    maxIdle = 10
    initialSize = 10
    minEvictableIdleTimeMillis = 1800000
    timeBetweenEvictionRunsMillis = 1800000
    maxWait = 10000
    testWhileIdle = true
    numTestsPerEvictionRun = 3
    testOnBorrow = true
}

}
hibernate {
cache.use_second_level_cache = true
cache.use_query_cache = true
cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider'
}
1
are u implementing ControllerUnitTestCase? or just UnitTestCase?! - Arthur Neves
Could you post your DataSource.groovy file? - Arthur Neves
ok, But I mean you should be injecting your new implementation of Datasource in the spring file right(resources.groovy), how are you doing that?! are you forcing to inject that datasource in the service also!? - Arthur Neves
As part of the resources we are creating a dataSource bean. So it ends up being beans = { ... dataSource(CustomDataSource){...}} if that makes sense. The issue is that it works perfectly fine when running as a webapp, but fails miserably just in integration tests. Its like the getConnection calls aren't being done at the appropriate times in the integration tests. - Joseph

1 Answers

2
votes

This is not a final Answer, however I believe this is an explanation of what is going on:

  • Running as Web app: your Service class has a transactionManager which has a sessionFactory, which gets the connection! So in this case, assuming that you Service is 'transactional=true' all methods that you call in your services will have a 'Session.beginTransaction()' in the beginning of the method(there is a Grails`s Proxy to do that, when you set 'transactional=true'), which will call all that stack until getConnection().

  • Running as Integration Test: as Grails doesnt commit your DB changes, it always rollback them! I believe that when you are starting your Integration test, grails is creating a transaction right away! so it will be able to rollback it afterwards!(which make totally sense right!), you can confirm that taking a look at the class org.codehaus.groovy.grails.test.support.GrailsTestInterceptor. The method init() is called before your services in your integration test. So that`s why getConnection() is being called before everything!

Suggestion: You can try setting your integration test class as 'transaction=false' and see if getConnection() doesn't get call in the beginning! Go to Transactions section in here to see more! Just dont forget that in your test you will have to rollback your transaction! if your set transaction=false.