You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@grails.apache.org by bo...@apache.org on 2026/04/09 14:53:18 UTC
(grails-core) 37/40: fix: make gorm and app1 functional tests H7-compatible
This is an automated email from the ASF dual-hosted git repository.
borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 29697cdc5b140d400a164266ebed7c8af40e51a2
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Wed Apr 8 13:27:58 2026 -0500
fix: make gorm and app1 functional tests H7-compatible
- Fix 17 plain executeUpdate('...') calls across 7 specs in
grails-test-examples/gorm to use executeUpdate('...', [:]).
H7's HibernateGormStaticApi rejects plain CharSequence args
(requires either a GString with interpolated params or the
Map overload).
- Add getDomainClasses() override to BookHibernateSpec in app1.
H7's HibernateSpec uses HibernateDatastoreSpringInitializer
which requires explicit domain class declaration; H5 auto-detected
via classpath scanning.
- Remove grails-test-examples-app1 and grails-test-examples-gorm
from h7IncompatibleProjects list — both now run cleanly under
Hibernate 7 via dependency substitution.
Remaining excluded: datasources (ChainedTransactionManager),
views-functional-tests (HAL/JSON diffs), scaffolding-fields
(grails-fields rendering diffs).
Co-authored-by: Copilot <22...@users.noreply.github.com>
---
gradle/functional-test-config.gradle | 52 ++++++++++++++++++++++
.../functionaltests/BookHibernateSpec.groovy | 3 ++
.../groovy/gorm/GormCascadeOperationsSpec.groovy | 8 ++--
.../groovy/gorm/GormCriteriaQueriesSpec.groovy | 4 +-
.../groovy/gorm/GormDataServicesSpec.groovy | 4 +-
.../groovy/gorm/GormEventsSpec.groovy | 2 +-
.../groovy/gorm/GormWhereQueryAdvancedSpec.groovy | 4 +-
.../groovy/gorm/TransactionPropagationSpec.groovy | 4 +-
...TransactionalWhereQueryVariableScopeSpec.groovy | 4 +-
9 files changed, 70 insertions(+), 15 deletions(-)
diff --git a/gradle/functional-test-config.gradle b/gradle/functional-test-config.gradle
index f05b04afb8..9f75ff67d4 100644
--- a/gradle/functional-test-config.gradle
+++ b/gradle/functional-test-config.gradle
@@ -21,6 +21,23 @@ rootProject.subprojects
.findAll { !(it.name in testProjects) && !(it.name in docProjects) && !(it.name in cliProjects) }
.each { project.evaluationDependsOn(it.path) }
+// Determine which Hibernate version to use for general functional tests.
+// Pass -PhibernateVersion=7 to run general functional tests against Hibernate 7 instead of 5.
+def targetHibernateVersion = project.findProperty('hibernateVersion') ?: '5'
+boolean isHibernateSpecificProject = project.name.startsWith('grails-test-examples-hibernate5') ||
+ project.name.startsWith('grails-test-examples-hibernate7')
+boolean isMongoProject = project.name.startsWith('grails-test-examples-mongodb')
+boolean isGeneralFunctionalTest = !isHibernateSpecificProject && !isMongoProject
+
+// General functional test projects that use Hibernate 5-specific GORM APIs and cannot run
+// under Hibernate 7 via dependency substitution.
+// Their H7-compatible equivalents live in grails-test-examples/hibernate7/.
+List<String> h7IncompatibleProjects = [
+ 'grails-test-examples-datasources',
+ 'grails-test-examples-views-functional-tests',
+ 'grails-test-examples-scaffolding-fields',
+]
+
configurations.configureEach {
resolutionStrategy.dependencySubstitution {
// Test projects will often include dependencies from local projects. This will ensure any dependencies
@@ -51,6 +68,22 @@ configurations.configureEach {
}
}
}
+
+ // For general (non-hibernate-labeled) functional test projects, redirect Hibernate 5 dependencies
+ // to Hibernate 7 projects when -PhibernateVersion=7 is set. These rules are added after the loop
+ // so they override the default substitutions for the h5 modules.
+ // Projects in h7IncompatibleProjects are excluded since they use H5-specific GORM APIs.
+ if (isGeneralFunctionalTest && targetHibernateVersion == '7' && !(project.name in h7IncompatibleProjects)) {
+ substitute module('org.apache.grails:grails-data-hibernate5') using project(':grails-data-hibernate7')
+ substitute module('org.apache.grails:grails-data-hibernate5-spring-boot') using project(':grails-data-hibernate7-spring-boot')
+ }
+ }
+
+ // Exclude Hibernate 5-specific runtime dependencies when testing general projects with Hibernate 7.
+ // These libraries have no Hibernate 7 equivalent and would cause classpath conflicts.
+ if (isGeneralFunctionalTest && targetHibernateVersion == '7' && !(project.name in h7IncompatibleProjects)) {
+ exclude group: 'org.hibernate', module: 'hibernate-ehcache'
+ exclude group: 'org.jboss.spec.javax.transaction', module: 'jboss-transaction-api_1.3_spec'
}
}
@@ -68,6 +101,11 @@ tasks.withType(Test).configureEach { Test task ->
return false
}
+ // Skip projects with known H7 API incompatibilities when running with hibernateVersion=7
+ if (targetHibernateVersion == '7' && project.name in h7IncompatibleProjects) {
+ return false
+ }
+
if (project.hasProperty('onlyHibernate5Tests')) {
if (isHibernate5) {
return false
@@ -80,6 +118,20 @@ tasks.withType(Test).configureEach { Test task ->
}
}
+ // Skip hibernate5-labeled projects when -PskipHibernate5Tests is set
+ if (project.hasProperty('skipHibernate5Tests')) {
+ if (!isHibernate5) {
+ return false
+ }
+ }
+
+ // Skip hibernate7-labeled projects when -PskipHibernate7Tests is set
+ if (project.hasProperty('skipHibernate7Tests')) {
+ if (!isHibernate7) {
+ return false
+ }
+ }
+
if (project.hasProperty('onlyMongodbTests')) {
if (isMongo) {
return false
diff --git a/grails-test-examples/app1/src/test/groovy/functionaltests/BookHibernateSpec.groovy b/grails-test-examples/app1/src/test/groovy/functionaltests/BookHibernateSpec.groovy
index 958f52585b..0fb97ce9d4 100644
--- a/grails-test-examples/app1/src/test/groovy/functionaltests/BookHibernateSpec.groovy
+++ b/grails-test-examples/app1/src/test/groovy/functionaltests/BookHibernateSpec.groovy
@@ -21,6 +21,9 @@ package functionaltests
class BookHibernateSpec extends grails.test.hibernate.HibernateSpec {
+ @Override
+ List<Class> getDomainClasses() { [Book] }
+
def setup() {
new Book(title: 'foo').save()
}
diff --git a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormCascadeOperationsSpec.groovy b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormCascadeOperationsSpec.groovy
index 931db50d6e..11b9a722cf 100644
--- a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormCascadeOperationsSpec.groovy
+++ b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormCascadeOperationsSpec.groovy
@@ -41,10 +41,10 @@ class GormCascadeOperationsSpec extends Specification {
def setup() {
// Clean up test data
- Book.executeUpdate('delete from Book')
- Author.executeUpdate('delete from Author')
- User.executeUpdate('delete from User')
- City.executeUpdate('delete from City')
+ Book.executeUpdate('delete from Book', [:])
+ Author.executeUpdate('delete from Author', [:])
+ User.executeUpdate('delete from User', [:])
+ City.executeUpdate('delete from City', [:])
}
// ============================================
diff --git a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormCriteriaQueriesSpec.groovy b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormCriteriaQueriesSpec.groovy
index b73c87d977..920f9e9ed2 100644
--- a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormCriteriaQueriesSpec.groovy
+++ b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormCriteriaQueriesSpec.groovy
@@ -37,8 +37,8 @@ class GormCriteriaQueriesSpec extends Specification {
def setup() {
// Clean up and create fresh test data
- Book.executeUpdate('delete from Book')
- Author.executeUpdate('delete from Author')
+ Book.executeUpdate('delete from Book', [:])
+ Author.executeUpdate('delete from Author', [:])
def kingAuthor = new Author(name: 'Stephen King', email: 'stephen@king.com').save(flush: true)
def clancyAuthor = new Author(name: 'Tom Clancy', email: 'tom@clancy.com').save(flush: true)
diff --git a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormDataServicesSpec.groovy b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormDataServicesSpec.groovy
index 277fe14220..b8625820ca 100644
--- a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormDataServicesSpec.groovy
+++ b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormDataServicesSpec.groovy
@@ -48,8 +48,8 @@ class GormDataServicesSpec extends Specification {
def setup() {
// Clean up and create fresh test data
- Book.executeUpdate('delete from Book')
- Author.executeUpdate('delete from Author')
+ Book.executeUpdate('delete from Book', [:])
+ Author.executeUpdate('delete from Author', [:])
def author = new Author(name: 'Stephen King', email: 'stephen@king.com').save(flush: true)
diff --git a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormEventsSpec.groovy b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormEventsSpec.groovy
index 2f9dd463bb..43cc06e984 100644
--- a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormEventsSpec.groovy
+++ b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormEventsSpec.groovy
@@ -42,7 +42,7 @@ import grails.testing.mixin.integration.Integration
class GormEventsSpec extends Specification {
def setup() {
- AuditedEntity.executeUpdate('delete from AuditedEntity')
+ AuditedEntity.executeUpdate('delete from AuditedEntity', [:])
}
// ============================================
diff --git a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormWhereQueryAdvancedSpec.groovy b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormWhereQueryAdvancedSpec.groovy
index c7d339dc55..cdfafab806 100644
--- a/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormWhereQueryAdvancedSpec.groovy
+++ b/grails-test-examples/gorm/src/integration-test/groovy/gorm/GormWhereQueryAdvancedSpec.groovy
@@ -39,8 +39,8 @@ class GormWhereQueryAdvancedSpec extends Specification {
def setup() {
// Clean up existing data
- Book.executeUpdate('delete from Book')
- Author.executeUpdate('delete from Author')
+ Book.executeUpdate('delete from Book', [:])
+ Author.executeUpdate('delete from Author', [:])
// Create test authors
def king = new Author(name: 'Stephen King', email: 'stephen@king.com').save(flush: true)
diff --git a/grails-test-examples/gorm/src/integration-test/groovy/gorm/TransactionPropagationSpec.groovy b/grails-test-examples/gorm/src/integration-test/groovy/gorm/TransactionPropagationSpec.groovy
index a60e1678de..8304bfa240 100644
--- a/grails-test-examples/gorm/src/integration-test/groovy/gorm/TransactionPropagationSpec.groovy
+++ b/grails-test-examples/gorm/src/integration-test/groovy/gorm/TransactionPropagationSpec.groovy
@@ -44,8 +44,8 @@ class TransactionPropagationSpec extends Specification {
def setup() {
// Clean up before each test - delete books first due to FK constraint
Author.withNewTransaction {
- Book.executeUpdate('delete from Book')
- Author.executeUpdate('delete from Author')
+ Book.executeUpdate('delete from Book', [:])
+ Author.executeUpdate('delete from Author', [:])
}
}
diff --git a/grails-test-examples/gorm/src/integration-test/groovy/gorm/TransactionalWhereQueryVariableScopeSpec.groovy b/grails-test-examples/gorm/src/integration-test/groovy/gorm/TransactionalWhereQueryVariableScopeSpec.groovy
index 972812ded2..20f9a56bd3 100644
--- a/grails-test-examples/gorm/src/integration-test/groovy/gorm/TransactionalWhereQueryVariableScopeSpec.groovy
+++ b/grails-test-examples/gorm/src/integration-test/groovy/gorm/TransactionalWhereQueryVariableScopeSpec.groovy
@@ -45,8 +45,8 @@ class TransactionalWhereQueryVariableScopeSpec extends Specification {
WhereQueryVariableScopeService whereQueryVariableScopeService
def setup() {
- Book.executeUpdate('delete from Book')
- Author.executeUpdate('delete from Author')
+ Book.executeUpdate('delete from Book', [:])
+ Author.executeUpdate('delete from Author', [:])
def king = new Author(name: 'Stephen King', email: 'stephen@king.com').save(flush: true)
def clancy = new Author(name: 'Tom Clancy', email: 'tom@clancy.com').save(flush: true)