This problem has cropped up several times over the years. We never tracked down the problem until we
spent some hours debugging the spring startup logic when used with an IDE test runner (Intellij).
This also affects tests run from Gradle.
The problem is that the Grails application would restart between integration tests under some conditions.
This slowed things down a lot and caused errors.
Symptoms:
- The first test class starts up fine.
- This first class initializes the Grails context correctly.
- All tests in the first test class runs correctly.
- The second test class then starts up.
- This attempts to start a new Grails context, which conflicts with the original.
- This normally fails with a session not found exception, but sometimes it is a listener port already in use error.
The example output is shown below:
Configuring Spring Security Core ...
... finished configuring Spring Security Core
Grails application running at http://localhost:64901 in environment: test
Configuring Spring Security Core ...
... finished configuring Spring Security Core
Grails application running at http://localhost:64901 in environment: test
org.hibernate.HibernateException: No Session found for current thread
at org.grails.orm.hibernate.GrailsSessionContext.currentSession(GrailsSessionContext.java:117)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:688)
at org.grails.orm.hibernate.HibernateSession.createQuery(HibernateSession.java:177)
at org.grails.orm.hibernate.HibernateSession.createQuery(HibernateSession.java:170)
. . .
Root Cause:
The root cause is that the tests had different super-class hierarchies. One test had an @Integration
annotation and its super-class also had an @Integration annotation. In the internals of Spring
(AbstractTestContextBootstrapper.buildMergedContextConfiguration()), the MergedContextConfiguration
internally refers to two Application classes. The other test class on referred to one Application class,
so Spring thinks they are two different application contexts. Spring then tries to start the application again.
Fix:
Make sure your test classes have the @Integration annotation just once in their hierarchies (at the test
class itself).
Also, it turns out there is no need for the @Integration annotation in the super-class.