11package graphql
22
3+ import graphql.execution.ExecutorServiceExecutionStrategy
4+ import graphql.execution.SimpleExecutionStrategy
35import graphql.schema.GraphQLOutputType
46import graphql.schema.GraphQLSchema
57import spock.lang.Specification
@@ -9,18 +11,24 @@ import static graphql.schema.GraphQLFieldDefinition.newFieldDefinition
911import static graphql.schema.GraphQLNonNull.nonNull
1012import static graphql.schema.GraphQLObjectType.newObject
1113import static graphql.schema.GraphQLSchema.newSchema
14+ import static java.util.concurrent.ForkJoinPool.commonPool
1215
1316/**
1417 * A set of tests to show how non null field handling correctly bubble up or not
1518 */
19+ @SuppressWarnings (" GroovyUnusedDeclaration" )
1620class NonNullHandlingTest extends Specification {
1721
18- @SuppressWarnings (" GroovyUnusedDeclaration" )
19- class ParentTypeImplementation {
22+ class SimpleObject {
2023 String nullChild = null
2124 String nonNullChild = " not null"
2225 }
2326
27+ class ContainingObject {
28+ SimpleObject nullParent = null
29+ SimpleObject nonNullParent = new SimpleObject ()
30+ }
31+
2432 def executionInput (String query ) {
2533 ExecutionInput . newExecutionInput(). query(query). build()
2634 }
@@ -46,7 +54,7 @@ class NonNullHandlingTest extends Specification {
4654 .field(newFieldDefinition()
4755 .name(" parent" )
4856 .type(parentType) // nullable parent
49- .dataFetcher({ env -> new ParentTypeImplementation () })
57+ .dataFetcher({ env -> new SimpleObject () })
5058
5159 ))
5260 .build()
@@ -60,13 +68,22 @@ class NonNullHandlingTest extends Specification {
6068 }
6169 """
6270
63- when :
64- def result = GraphQL . newGraphQL(schema). build(). execute(executionInput(query))
71+ def result = GraphQL
72+ .newGraphQL(schema)
73+ .queryExecutionStrategy(executionStrategy)
74+ .build()
75+ .execute(executionInput(query))
6576
66- then :
77+ expect :
6778
6879 result. errors. size() == 1
6980 result. data[" parent" ] == null
81+
82+ where :
83+
84+ strategyName | executionStrategy
85+ ' executor' | new ExecutorServiceExecutionStrategy (commonPool())
86+ ' simple' | new SimpleExecutionStrategy ()
7087 }
7188
7289 def " #268 - null child field values are NOT allowed in non nullable parent types" () {
@@ -91,7 +108,7 @@ class NonNullHandlingTest extends Specification {
91108 newFieldDefinition()
92109 .name(" parent" )
93110 .type(nonNull(parentType)) // non nullable parent
94- .dataFetcher({ env -> new ParentTypeImplementation () })
111+ .dataFetcher({ env -> new SimpleObject () })
95112
96113 ))
97114 .build()
@@ -105,12 +122,151 @@ class NonNullHandlingTest extends Specification {
105122 }
106123 """
107124
108- when :
109- def result = GraphQL . newGraphQL(schema). build(). execute(executionInput(query))
125+ def result = GraphQL
126+ .newGraphQL(schema)
127+ .queryExecutionStrategy(executionStrategy)
128+ .build()
129+ .execute(executionInput(query))
110130
111- then :
131+ expect :
112132
113133 result. errors. size() == 1
114134 result. data == null
135+
136+ where :
137+
138+ strategyName | executionStrategy
139+ ' executor' | new ExecutorServiceExecutionStrategy (commonPool())
140+ ' simple' | new SimpleExecutionStrategy ()
115141 }
142+
143+ def " #581 - null child field values are allowed in nullable grand parent type" () {
144+
145+ given :
146+
147+
148+ GraphQLOutputType parentType = newObject()
149+ .name(" parentType" )
150+ .field(newFieldDefinition(). name(" nullChild" )
151+ .type(nonNull(GraphQLString )))
152+ .field(newFieldDefinition(). name(" nonNullChild" )
153+ .type(nonNull(GraphQLString )))
154+ .build()
155+
156+ GraphQLOutputType topType = newObject()
157+ .name(" topType" )
158+ .field(newFieldDefinition(). name(" nullParent" )
159+ .type(nonNull(parentType)))
160+ .field(newFieldDefinition(). name(" nonNullParent" )
161+ .type(nonNull(parentType)))
162+ .build()
163+
164+ GraphQLSchema schema = newSchema(). query(
165+ newObject()
166+ .name(" RootQueryType" )
167+ .field(
168+ newFieldDefinition()
169+ .name(" top" )
170+ .type(topType) // nullable grand parent
171+ .dataFetcher({ env -> new ContainingObject () })
172+
173+ ))
174+ .build()
175+
176+ def query = """
177+ query {
178+ top {
179+ nonNullParent {
180+ nonNullChild
181+ nullChild
182+ }
183+ }
184+ }
185+ """
186+
187+ def result = GraphQL
188+ .newGraphQL(schema)
189+ .queryExecutionStrategy(executionStrategy)
190+ .build()
191+ .execute(executionInput(query))
192+
193+ expect :
194+
195+ result. errors. size() == 1
196+ result. data != null
197+ result. data[" grandParent" ] == null
198+
199+ where :
200+
201+ strategyName | executionStrategy
202+ ' executor' | new ExecutorServiceExecutionStrategy (commonPool())
203+ ' simple' | new SimpleExecutionStrategy ()
204+
205+ }
206+
207+ def " #581 - null child field values are NOT allowed in non nullable grand parent types" () {
208+
209+ given :
210+
211+
212+ GraphQLOutputType parentType = newObject()
213+ .name(" parentType" )
214+ .field(newFieldDefinition(). name(" nullChild" )
215+ .type(nonNull(GraphQLString )))
216+ .field(newFieldDefinition(). name(" nonNullChild" )
217+ .type(nonNull(GraphQLString )))
218+ .build()
219+
220+ GraphQLOutputType topType = newObject()
221+ .name(" topType" )
222+ .field(newFieldDefinition(). name(" nullParent" )
223+ .type(nonNull(parentType)))
224+ .field(newFieldDefinition(). name(" nonNullParent" )
225+ .type(nonNull(parentType)))
226+ .build()
227+
228+ GraphQLSchema schema = newSchema(). query(
229+ newObject()
230+ .name(" RootQueryType" )
231+ .field(
232+ newFieldDefinition()
233+ .name(" top" )
234+ .type(nonNull(topType)) // non nullable grand parent
235+ .dataFetcher({ env -> new ContainingObject () })
236+
237+ ))
238+ .build()
239+
240+ def query = """
241+ query {
242+ top {
243+ nonNullParent {
244+ nonNullChild
245+ nullChild
246+ }
247+ }
248+ }
249+ """
250+
251+ def result = GraphQL
252+ .newGraphQL(schema)
253+ .queryExecutionStrategy(executionStrategy)
254+ .build()
255+ .execute(executionInput(query))
256+
257+ expect :
258+
259+ result != null
260+ result. errors. size() == 1
261+ result. data == null
262+
263+ where :
264+
265+ strategyName | executionStrategy
266+ ' executor' | new ExecutorServiceExecutionStrategy (commonPool())
267+ ' simple' | new SimpleExecutionStrategy ()
268+
269+ }
270+
271+
116272}
0 commit comments