Skip to content

test: raise coverage in grails-data-hibernate7 - #16278

Open
borinquenkid wants to merge 7 commits into
8.1.xfrom
test/grails-data-hibernate7-coverage
Open

test: raise coverage in grails-data-hibernate7#16278
borinquenkid wants to merge 7 commits into
8.1.xfrom
test/grails-data-hibernate7-coverage

Conversation

@borinquenkid

Copy link
Copy Markdown
Member

Summary

  • Closes real JaCoCo coverage gaps in grails-data-hibernate7 (both the core and grails-plugin subprojects) — no production code changes, tests only.
  • AggregatePersistenceContextInterceptor: 24.5% → 86.8% (no dedicated Spec existed for the multi-datasource lifecycle fan-out).
  • HibernateCriteriaBuilder: 72.7% → 89.6%, PredicateGenerator: 83.2% → 85.2% (extended the existing "low-level method coverage" Direct spec: createAlias, exists/notExists closures, eqAll/gtSome/geSome/ltSome/leSome, notIn, inList, ignoreCase eq, plus the documented PredicateGenerator.registerCriterionHandler extension point).
  • DetachedAssociationFunction: 50% → 100%, IdentityEnumType: 65.6% → 91.8% (BidiEnumMap → 100%).
  • GrailsHibernateUtil: 77.9% → 85.3% (proxy-unwrap branches reached by explicitly initializing a Hibernate proxy after clearing the session, plus the single-arg delegate overloads).
  • ManyToOneBinder: 78.2% → 100% (composite-identity join-key derivation for circular many-to-many associations).
  • ChildHibernateDatastore: 80% → 100%, SelectHqlQuery: 82.9% → 100%, JpaQueryContext: 78.5% → 95.4%.
  • HibernateGrailsPlugin: 0% → 100% — added a new HibernateGrailsPluginSpec that drives doWithSpring() through a BeanBuilder, following the existing QuartzGrailsPluginSpec pattern (no plugin manager or full app bootstrap needed).

Module totals: core 93.6% → 94.9%, grails-plugin 63.7% → 77.8%.

A couple of items were deliberately left alone and are not part of this PR:

  • HibernateQueryConstants and ProjectionPredicate are unreferenced/deprecated dead code — flagged as removal candidates rather than given tests to inflate coverage on code nothing calls.
  • A handful of defensive "unsupported X" exception branches and TRACE-level log lines in GrailsHibernateUtil/PredicateGenerator aren't reachable through the public Groovy-compiled API surface in this module.

Test plan

  • ./gradlew :grails-data-hibernate7-core:test — full suite green (3101 tests)
  • ./gradlew :grails-data-hibernate7:test — full suite green (28 tests)
  • ./gradlew :grails-data-hibernate7-core:codeStyle :grails-data-hibernate7:codeStyle — clean
  • JaCoCo reports regenerated after each change to confirm real coverage movement (not stale cached reports)

🤖 Generated with Claude Code

https://claude.ai/code/session_01QAjfckcY4EJsxranv1RyGV

borinquenkid and others added 7 commits August 30, 2026 16:15
AbstractMultipleDataSourceAggregatePersistenceContextInterceptor had no
dedicated Spec and sat at 24.5% line coverage despite fanning out
lifecycle calls (init/destroy/flush/clear/isOpen/setReadOnly/
setReadWrite/disconnect/reconnect) across every configured data source.
New Spec drives its concrete AggregatePersistenceContextInterceptor
subclass through a two-datasource HibernateDatastore, raising coverage
to 86.8%.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QAjfckcY4EJsxranv1RyGV
HibernateCriteriaBuilder sat at 72.7% line coverage and PredicateGenerator
at 83.2%, with several DSL methods (createAlias, exists/notExists with an
inline closure, join/lock/cache/readOnly/select hints, eqAll/gtSome/geSome/
ltSome/leSome, notIn, inList, ignoreCase eq) never exercised through the
criteria DSL. Adds targeted cases to the existing "for low-level method
coverage (JaCoCo line hits)" Direct spec, plus a case driving the
documented PredicateGenerator.registerCriterionHandler extension point.

HibernateCriteriaBuilder: 72.7% -> 89.6%. PredicateGenerator: 83.2% -> 85.2%.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QAjfckcY4EJsxranv1RyGV
DetachedAssociationFunction (50%) never had a case for the recursive
Query.Junction-flattening branch. IdentityEnumType (65.6%) was missing
its error/fallback paths in setParameterValues (unloadable class,
Class-attribute fallback, missing enumClass), the BIGINT/VARCHAR jdbc
type selection branches, getBidiEnumMap's reflection-failure and
duplicate-id-warning paths, disassemble/assemble, and nullSafeSet's
null branch — all exercised directly through IdentityEnumType's public
UserType/ParameterizedType contract methods.

DetachedAssociationFunction: 50% -> 100%.
IdentityEnumType: 65.6% -> 91.8% (BidiEnumMap: 88.9% -> 100%).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QAjfckcY4EJsxranv1RyGV
setObjectToReadyOnly/setObjectToReadWrite's HibernateProxy-unwrap branches
were never hit: canModifyReadWriteState requires the target to already be
initialized, and prior tests fetched proxies via getReference() while the
entity was still session-managed from an earlier statement, so Hibernate
handed back the real instance instead of a proxy. Clearing the session
before getReference() forces a genuine lazy proxy, which is then
explicitly initialized while remaining a HibernateProxy reference,
reaching the unwrap branch in both methods. Also adds cases for the
single-argument unwrapProxy/getAssociationProxy/isInitialized/
unwrapIfProxy convenience overloads that delegate to the default proxy
handler.

GrailsHibernateUtil: 77.9% -> 85.3%. The remaining gap is the
annotation-name-string branch in isDomainClass (grails.persistence.Entity
and JPA @entity classes compiled in this project already implement
GormEntity via the GORM AST transform before that branch is reached) and
two TRACE-level log lines — not reachable through this module's public
Groovy-compiled surface.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QAjfckcY4EJsxranv1RyGV
prepareCircularManyToMany's composite-identity branch (building join
table keys for a self-referential many-to-many owned by an entity with
a composite identity) was untested: neither the "reuse existing
matching join keys" path nor the "derive keys from property names via
the naming strategy" path was exercised.

ManyToOneBinder: 78.2% -> 100%.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QAjfckcY4EJsxranv1RyGV
…ectHqlQuery

ChildHibernateDatastore: destroy() (marking destroyed without closing the
parent's shared session factory) had no case.

JpaQueryContext: the aliases-only/parent-only constructor overloads, the
forRoot(aliases, root) static factory, setParent, getAliasedExpression's
parent-delegation when not realized locally, the "{alias}" and
"{alias}.path" token-resolution delegation to a parent context, and
clone() were all untested.

SelectHqlQuery: the max/offset builder-method-set fields branch in
applyQuerySettings/getMax/getOffset (as opposed to the query-args-map
branch already covered), the no-op setReadOnly compatibility method, and
executeQuery's delegation to list() were untested.

ChildHibernateDatastore: 80% -> 100%. SelectHqlQuery: 82.9% -> 100%.
JpaQueryContext: 78.5% -> 95.4%.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QAjfckcY4EJsxranv1RyGV
HibernateGrailsPlugin.doWithSpring() (the plugin descriptor's Spring
bean-wiring closure) had 0% coverage. Following the existing repo
pattern for testing Plugin subclasses in isolation (see
QuartzGrailsPluginSpec), the closure is driven directly through a
BeanBuilder against a plain DefaultGrailsApplication and
GenericApplicationContext, with no plugin manager or full application
bootstrap required. Covers bean-definition registration, the
dataSourceNames side effect, the PropertySourcesConfig conversion-service
installation branch (including invoking the registered String->Class
converter), the domain-class artefact collection, and the no-op
onChange() override.

HibernateGrailsPlugin (and its doWithSpring closure / anonymous
Converter): 0% -> 100%. grails-plugin module overall: 63.7% -> 77.8%.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QAjfckcY4EJsxranv1RyGV
Copilot AI lite review requested due to automatic review settings August 30, 2026 22:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@borinquenkid borinquenkid moved this to In Progress in Apache Grails Aug 30, 2026
@borinquenkid borinquenkid added this to the grails:8.1.0-M1 milestone Aug 30, 2026
@testlens-app

testlens-app Bot commented Aug 30, 2026

Copy link
Copy Markdown

🚨 TestLens detected 1 failed test 🚨

Here is what you can do:

  1. Inspect the test failures carefully.
  2. If you are convinced that some of the tests are flaky, you can mute them below.
  3. Finally, trigger a rerun by checking the rerun checkbox.

Test Summary

CI / Functional Tests (Java 25, indy=false, shard 1) > :grails-test-examples-gsp-sitemesh3:integrationTest

Test Runs Flakiness
EndToEndSpec > async multiple levels of layouts 1% 🟡

🏷️ Commit: 7fce7d8
▶️ Tests: 68736 executed
⚪️ Checks: 83/83 completed

Test Failures

EndToEndSpec > async multiple levels of layouts (:grails-test-examples-gsp-sitemesh3:integrationTest in CI / Functional Tests (Java 25, indy=false, shard 1))
Condition not satisfied:

pageSource == """<html><head><title>Decorated Base - Dialog - This is the title</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head> <body><h1>Hello</h1><div id="base"><div id="dialog">body text</div></div> </body></html>"""
|          |
|          false
|          Strings too large to calculate edit distance.
<html lang="en"><head><title>HTTP Status 500 – Internal Server Error</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 500 – Internal Server Error</h1></body></html>

	at EndToEndSpec.async multiple levels of layouts(EndToEndSpec.groovy:107)
expected actual
<html><head><title>Decorated Base - Dialog - This is the title</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head> <html lang="en"><head><title>HTTP Status 500 Internal Server Error</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 500 – Internal Server Error</h1></body></html>
<body><h1>Hello</h1><div id="base"><div id="dialog">body text</div></div>
</body></html>

Rerun Controls

Select tests to mute in this pull request:

  • EndToEndSpec > async multiple levels of layouts

Reuse successful test results:

  • ♻️ Only rerun the tests that failed or were muted before

Click the checkbox to trigger a rerun:

  • Rerun jobs

Learn more about TestLens at testlens.app/docs.

@codecov

codecov Bot commented Aug 30, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 29.8834%. Comparing base (bb21a3a) to head (7fce7d8).

Additional details and impacted files

Impacted file tree graph

@@              Coverage Diff              @@
##                8.1.x     #16278   +/-   ##
=============================================
  Coverage     29.8834%   29.8834%           
  Complexity        509        509           
=============================================
  Files              79         79           
  Lines            4715       4715           
  Branches          814        814           
=============================================
  Hits             1409       1409           
  Misses           3063       3063           
  Partials          243        243           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants