Add test coverage for AbstractDetachedCriteria and rx DetachedCriteria - #16143
Add test coverage for AbstractDetachedCriteria and rx DetachedCriteria#16143borinquenkid wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This pull request significantly expands unit test coverage around detached criteria usage in both the core (AbstractDetachedCriteria via grails.gorm.DetachedCriteria) and reactive (grails.gorm.rx.DetachedCriteria) stacks, while also fixing reactive subquery handling and simplifying query preparation behavior.
Changes:
- Add extensive mock-based Spock specs to drive high line/method coverage for
AbstractDetachedCriteriaand reactiveDetachedCriteria. - Fix reactive closure-based subqueries by introducing a
QueryableCriteria-compatibleSubqueryAdapter(avoids runtimeClassCastException). - Simplify reactive
prepareQuery()by removing redundant fetch-strategy application and relying onDynamicFinder.applyDetachedCriteria().
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| grails-datamapping-rx/src/test/groovy/org/grails/gorm/rx/api/DetachedCriteriaQuerySpec.groovy | New spec covering reactive query execution paths that go through prepareQuery() and static API lookup. |
| grails-datamapping-rx/src/test/groovy/grails/gorm/rx/DetachedCriteriaSpec.groovy | New spec verifying reactive DetachedCriteria override methods delegate correctly and return the narrowed type. |
| grails-datamapping-rx/src/main/groovy/grails/gorm/rx/DetachedCriteria.groovy | Fix reactive subquery construction and remove redundant fetch-strategy application during query preparation. |
| grails-datamapping-core/src/test/groovy/org/grails/datastore/gorm/query/criteria/AbstractDetachedCriteriaSpec.groovy | New comprehensive spec driving coverage of AbstractDetachedCriteria behavior via the concrete DetachedCriteria. |
| grails-datamapping-core/src/main/groovy/org/grails/datastore/gorm/query/criteria/AbstractDetachedCriteria.groovy | Small correctness/cleanup tweaks (definite assignment, safer list access, variable shadowing cleanup). |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
The suggestion to add a JoinType assertion to the test is appropriate. Verifying that |
…gy test Addresses Copilot review feedback on PR #16143: the existing fetch-strategy test only covered join(String)/select(String), not the JoinType-preserving behavior the removed duplicate loop had been silently discarding. Adds a dedicated test verifying query.join(property, joinType) is called when a custom JoinType is set. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.
Suppressed comments (1)
grails-datamapping-rx/src/test/groovy/org/grails/gorm/rx/api/DetachedCriteriaQuerySpec.groovy:42
- The class is public, so the Javadoc claim that it's "Package-local" is inaccurate. Either adjust the wording, or make the spec package-scoped (e.g., via @PackageScope) if that’s the intent.
* Package-local so the test can call the {@code protected static}
* {@code RxGormEnhancer.registerEntityWithConnectionSource} directly rather than driving the
* full {@code registerEntity} multi-tenancy/connection-source resolution machinery.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## 8.1.x #16143 +/- ##
==================================================
+ Coverage 52.8038% 52.8609% +0.0571%
- Complexity 18863 18903 +40
==================================================
Files 2079 2079
Lines 97207 97208 +1
Branches 16873 16873
==================================================
+ Hits 51329 51385 +56
+ Misses 38468 38418 -50
+ Partials 7410 7405 -5
🚀 New features to boost your workflow:
|
|
Let's just combine this PR with the other one? It looks like the tests that are commented were never uncommented and we can do all of this in one PR. @borinquenkid |
@jdaugherty I would prefer to keep them separate so they are as focused as possible |
Adds mock-based unit specs for AbstractDetachedCriteria (via grails.gorm.DetachedCriteria) and for the reactive grails.gorm.rx.DetachedCriteria, taking both from ~0% to full line/method coverage without needing a real datastore. Writing the rx specs surfaced two real bugs, both fixed here: - buildQueryableCriteria() cast the built DetachedCriteria to QueryableCriteria, but the rx class never implemented that interface, so every closure-based subquery (in, inList, notIn, eqAll/gtAll/ltAll/geAll/leAll, gtSome/geSome/ltSome/leSome) threw a ClassCastException at runtime. Fixed with a small SubqueryAdapter that extends the shared AbstractDetachedCriteria base directly, since the reactive class's own find()/list() return Observable and can't coexist with QueryableCriteria's T/List<T> signatures on the same type. - prepareQuery() applied fetch strategies (join/select) twice: once via DynamicFinder.applyDetachedCriteria(), then again via a redundant hand-rolled loop that also ignored custom JoinTypes. Removed the dead duplicate. Also fixes a handful of definite-assignment/shadowing/raw-getAt warnings in AbstractDetachedCriteria (uninitialized `prop` in createAlias, a local variable named `criteria` shadowing the instance field of the same name in clone(), and negative-index List access replaced with getLast()). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…gy test Addresses Copilot review feedback on PR #16143: the existing fetch-strategy test only covered join(String)/select(String), not the JoinType-preserving behavior the removed duplicate loop had been silently discarding. Adds a dedicated test verifying query.join(property, joinType) is called when a custom JoinType is set. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
7610e29 to
7de0bc6
Compare
✅ All tests passed ✅🏷️ Commit: 7de0bc6 Learn more about TestLens at testlens.app. |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 4 out of 4 changed files in this pull request and generated no new comments.
Suppressed comments (2)
grails-datamapping-rx/src/main/groovy/grails/gorm/rx/DetachedCriteria.groovy:653
- The extra cast chain
(Class<Observable<T>>) (Class) targetClassis redundant (sincetargetClassis already aClass), and it makes the intent harder to read. A single cast is enough here.
if (additionalCriteria != null) {
def additionalDetached = new DetachedCriteria((Class<Observable<T>>) (Class) targetClass).build(additionalCriteria)
DynamicFinder.applyDetachedCriteria(query, additionalDetached)
grails-datamapping-rx/src/test/groovy/org/grails/gorm/rx/api/DetachedCriteriaQuerySpec.groovy:119
- This spec name says
get(Closure)but the test actually callscriteria.get()with no closure. Renaming the feature text avoids confusion about which overload is being exercised.
void "get(Closure) applies a max of 1 and delegates to the no-arg RxQuery#singleResult"() {
Summary
AbstractDetachedCriteria(viagrails.gorm.DetachedCriteria) and for the reactivegrails.gorm.rx.DetachedCriteria, taking both from ~0% to full line/method coverage without needing a real datastore.buildQueryableCriteria()cast the builtDetachedCriteriatoQueryableCriteria, but the rx class never implemented that interface, so every closure-based subquery (in,inList,notIn,eqAll/gtAll/ltAll/geAll/leAll,gtSome/geSome/ltSome/leSome) threw aClassCastExceptionat runtime. Fixed with a smallSubqueryAdapterthat extends the sharedAbstractDetachedCriteriabase directly, since the reactive class's ownfind()/list()returnObservableand can't coexist withQueryableCriteria'sT/List<T>signatures on the same type.prepareQuery()applied fetch strategies (join/select) twice: once viaDynamicFinder.applyDetachedCriteria(), then again via a redundant hand-rolled loop that also ignored customJoinTypes. Removed the dead duplicate.getAtwarnings inAbstractDetachedCriteria(uninitializedpropincreateAlias, a local variable namedcriteriashadowing the instance field of the same name inclone(), and negative-indexListaccess replaced withgetLast()).Test plan
:grails-datamapping-core:test— 71 new tests inAbstractDetachedCriteriaSpec, all pass:grails-datamapping-rx:test— 45 new tests acrossDetachedCriteriaSpecandDetachedCriteriaQuerySpec, all pass:grails-datamapping-core:codeStyleand:grails-datamapping-rx:codeStylecleanjacocoTestReportthatAbstractDetachedCriteriaandgrails.gorm.rx.DetachedCriteria(plus its newSubqueryAdapter) are at ~100% line/method coverage🤖 Generated with Claude Code