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/08/23 16:04:33 UTC
(grails-core) 03/08: Restore null-safe getMergedField handling and cover ClosureDataFetcher.buildFetchOptions
This is an automated email from the ASF dual-hosted git repository.
borinquenkid pushed a commit to branch refactor/graphql-entity
in repository https://gitbox.apache.org/repos/asf/grails-core.git
commit 8c6e067feee0b7b48ee845b50aa2d927976ca119
Author: Walter Duque de Estrada <wb...@mac.com>
AuthorDate: Sat Aug 22 10:47:04 2026 -0500
Restore null-safe getMergedField handling and cover ClosureDataFetcher.buildFetchOptions
A prior commit in this cleanup ("Parameterize raw
Association/ToOne/Selection usages") accidentally dropped the
null-guard around environment.getMergedField() in
EntityFetchOptions.getJoinProperties(DataFetchingEnvironment, boolean)
while editing nearby code, turning a graceful "no merged field ->
empty fields list" fallback into a NullPointerException. This broke
6+ existing specs whose DataFetchingEnvironment mocks don't stub
getMergedField() (so it returns null, as real callers can also see).
Restored the guard as a single-assignment if/else.
Also adds test coverage for ClosureDataFetcher.buildFetchOptions(),
which had none: null domain type, non-GORM domain type, a real GORM
entity domain type, and that the built EntityFetchOptions is cached
across calls. Converts ClosureDataFetcherSpec to HibernateSpec to
back the GORM-entity case.
Co-Authored-By: Claude Sonnet 5 <no...@anthropic.com>
---
.../gorm/graphql/entity/EntityFetchOptions.java | 23 ++++++++-----
.../fetcher/impl/ClosureDataFetcherSpec.groovy | 40 ++++++++++++++++++++--
2 files changed, 52 insertions(+), 11 deletions(-)
diff --git a/grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/entity/EntityFetchOptions.java b/grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/entity/EntityFetchOptions.java
index b13d44ba07..03eb53ebf9 100644
--- a/grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/entity/EntityFetchOptions.java
+++ b/grails-data-graphql/core/src/main/groovy/org/grails/gorm/graphql/entity/EntityFetchOptions.java
@@ -211,17 +211,22 @@ public class EntityFetchOptions {
* @return The list of properties to eagerly fetch
*/
public Set<String> getJoinProperties(DataFetchingEnvironment environment, boolean skipCollections) {
-
MergedField environmentMergedField = environment.getMergedField();
- List<Field> fields = environmentMergedField
- .getFields()
- .stream()
- .filter(field -> field.getSelectionSet() != null)
- .flatMap(field -> field.getSelectionSet().getSelections().stream())
- .filter(Field.class::isInstance)
- .map(Field.class::cast)
- .collect(Collectors.toList());
+ List<Field> fields;
+ if (environmentMergedField == null) {
+ fields = new ArrayList<>();
+ }
+ else {
+ fields = environmentMergedField
+ .getFields()
+ .stream()
+ .filter(field -> field.getSelectionSet() != null)
+ .flatMap(field -> field.getSelectionSet().getSelections().stream())
+ .filter(Field.class::isInstance)
+ .map(Field.class::cast)
+ .collect(Collectors.toList());
+ }
return getJoinProperties(fields, skipCollections);
}
diff --git a/grails-data-graphql/core/src/test/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetcherSpec.groovy b/grails-data-graphql/core/src/test/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetcherSpec.groovy
index a5a721975c..cd8889d64a 100644
--- a/grails-data-graphql/core/src/test/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetcherSpec.groovy
+++ b/grails-data-graphql/core/src/test/groovy/org/grails/gorm/graphql/fetcher/impl/ClosureDataFetcherSpec.groovy
@@ -20,11 +20,15 @@
package org.grails.gorm.graphql.fetcher.impl
import graphql.schema.DataFetchingEnvironment
-import spock.lang.Specification
+import org.grails.gorm.graphql.HibernateSpec
+import org.grails.gorm.graphql.domain.general.toone.One
+import org.grails.gorm.graphql.entity.EntityFetchOptions
import spock.lang.Subject
@Subject(ClosureDataFetcher)
-class ClosureDataFetcherSpec extends Specification {
+class ClosureDataFetcherSpec extends HibernateSpec {
+
+ List<Class> getDomainClasses() { [One] }
void "test closure is called with the source argument"() {
given:
@@ -57,4 +61,36 @@ class ClosureDataFetcherSpec extends Specification {
then:
result == 'hello'
}
+
+ void "test buildFetchOptions returns null when no domain type is supplied"() {
+ given:
+ ClosureDataFetcher fetcher = new ClosureDataFetcher({})
+
+ expect:
+ fetcher.buildFetchOptions() == null
+ }
+
+ void "test buildFetchOptions returns null when the domain type is not a GORM entity"() {
+ given:
+ ClosureDataFetcher fetcher = new ClosureDataFetcher({}, String)
+
+ expect:
+ fetcher.buildFetchOptions() == null
+ }
+
+ void "test buildFetchOptions returns fetch options for a GORM entity domain type"() {
+ given:
+ ClosureDataFetcher fetcher = new ClosureDataFetcher({}, One)
+
+ expect:
+ fetcher.buildFetchOptions() instanceof EntityFetchOptions
+ }
+
+ void "test buildFetchOptions caches the result"() {
+ given:
+ ClosureDataFetcher fetcher = new ClosureDataFetcher({}, One)
+
+ expect:
+ fetcher.buildFetchOptions().is(fetcher.buildFetchOptions())
+ }
}