grails-core icon indicating copy to clipboard operation
grails-core copied to clipboard

Fix/hibernate session integration tests 14920

Open aether-dev07 opened this issue 4 months ago • 6 comments

I've successfully implemented a solution to address the Hibernate session and transaction issue in Grails integration tests. The solution provides a way for integration tests to run with the same transactional context
as the application.

What was implemented:

  1. @WithSession annotation (grails-testing-support-core/src/main/groovy/grails/testing/mixin/integration/WithSession.groovy): - New annotation that binds a Hibernate session without starting a transaction - Can be applied at class or method level - Supports specifying specific datasources
  2. Session binding infrastructure: - GrailsTestSessionInterceptor - Manages session binding without transactions - WithSessionSpecExtension - Spock extension for handling @WithSession - WithSessionTransformation - AST transformation for the annotation
  3. Enhanced test infrastructure: - Updated GrailsTestMode to support bindSession flag - Modified GrailsTestInterceptor to handle session-only binding - Updated IntegrationSpecConfigurerExtension to enable session binding by default
  4. Test examples: - WithSessionIntegrationSpec - Demonstrates usage of @WithSession - SessionBindingComparisonSpec - Shows differences between test modes
  5. Documentation: - Added comprehensive documentation in the integration testing guide

How it solves the problem:

The issue described three scenarios:

  • Without @Rollback: No session bound → tests fail for operations that work in the app
  • With @Rollback: Both session and transaction → tests pass for operations that fail in the app
  • With @WithSession: Session without transaction → tests match application behavior

The new @WithSession annotation provides a session binding that matches the OISV (Open Session In View) pattern
used in running applications, where:

  • SELECT operations work (session available)
  • save() without flush works (no transaction needed)
  • save(flush: true) fails without @Transactional (matches runtime behavior)

This ensures integration tests accurately reflect the application's runtime behavior, preventing false positives
and false negatives in test results.

aether-dev07 avatar Aug 21 '25 19:08 aether-dev07

@RAJ-debug858 Thank you. Can you resubmit with the a target branch of 7.0.x?

When I try to make this change I get "There are no new commits between base branch '7.0.x' and head branch 'fix/hibernate-session-integration-tests-14920'", so I am guessing some of your new commits are not present on your forked branch.

jamesfredley avatar Aug 21 '25 20:08 jamesfredley

FYI: you can add your branch as a remote, fetch, cherry-pick your change, and then adjust for where its supposed to be. GitHub is showing 10,000+ commits so my guess is this change was made against an earlier branch before we created the mono repo.

jdaugherty avatar Aug 22 '25 03:08 jdaugherty

@jamesfredley Thank you! I’ve rebased my changes onto the 7.0.x branch and force-pushed the updated branch. The PR now targets 7.0.x as requested.

aether-dev07 avatar Aug 22 '25 03:08 aether-dev07

  • grails-test-core/build.gradle (modified)
    • grails-testing-support-core/build.gradle (modified)
    • The moved files in grails-testing-support-core/src/main/groovy/org/grails/test/
    • grails-testing-support-core/src/main/resources/META-INF/services/org.spockframework.runtime.extension.IGlobalE
      xtension (modified)
    • The fixed Java file with the import change

aether-dev07 avatar Aug 22 '25 14:08 aether-dev07

Can't the test behavior be driven by whether the application uses OSIV?

jdaugherty avatar Aug 22 '25 14:08 jdaugherty

This needs refactored to be an optional feature vs replacing the existing feature.

jamesfredley avatar Sep 24 '25 15:09 jamesfredley