Skip to content

Commit eede0bf

Browse files
committed
Fail the field when the custom context class is missing from the GraphQLContext
1 parent 810582d commit eede0bf

2 files changed

Lines changed: 43 additions & 4 deletions

File tree

‎src/main/kotlin/graphql/kickstart/tools/resolver/MethodFieldResolver.kt‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,17 @@ internal class MethodFieldResolver(
102102
val firstTrailingParameter = field.inputValueDefinitions.size + search.firstArgumentIndex
103103
method.parameterTypes.slice(firstTrailingParameter until numberOfParameters).forEach { parameterType ->
104104
when (parameterType) {
105-
options.contextClass -> args.add { environment -> environment.graphQlContext[options.contextClass] }
106-
107105
GraphQLContext::class.java -> args.add { environment -> environment.graphQlContext }
106+
107+
options.contextClass -> args.add { environment ->
108+
environment.graphQlContext.get<Any>(parameterType) ?: throw ResolverError(
109+
"Resolver method '${method.declaringClass.name}.${method.name}' has a parameter of the context class " +
110+
"'${parameterType.name}', but the GraphQLContext has no value for it. Put it in the GraphQLContext under " +
111+
"the class key when building the ExecutionInput, for example " +
112+
"graphQLContext(mapOf(${parameterType.simpleName}::class.java to context))."
113+
)
114+
}
115+
108116
else -> args.add { environment -> environment }
109117
}
110118
}

‎src/test/kotlin/graphql/kickstart/tools/MethodFieldResolverDataFetcherTest.kt‎

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import kotlinx.coroutines.Dispatchers
1919
import kotlinx.coroutines.Job
2020
import kotlinx.coroutines.channels.Channel
2121
import kotlinx.coroutines.channels.ReceiveChannel
22+
import org.junit.Assert.assertThrows
23+
import org.junit.Assert.assertTrue
2224
import org.junit.Test
2325
import org.reactivestreams.Publisher
2426
import org.reactivestreams.tck.TestEnvironment
@@ -276,15 +278,44 @@ class MethodFieldResolverDataFetcherTest {
276278
}
277279

278280
@Test
279-
fun `data fetcher does not read custom context from the legacy context object`() {
281+
fun `data fetcher fails if custom context is missing from GraphQLContext`() {
280282
val options = SchemaParserOptions.newOptions().contextClass(ContextClass::class).build()
281283
val resolver = createFetcher("active", options = options, resolver = object : GraphQLResolver<DataClass> {
282284
fun isActive(dataClass: DataClass, ctx: ContextClass?): Boolean {
283285
return ctx != null
284286
}
285287
})
286288

287-
assertEquals(resolver.get(createEnvironment(DataClass(), legacyContext = ContextClass())), false)
289+
val error = assertThrows(ResolverError::class.java) { resolver.get(createEnvironment(DataClass())) }
290+
291+
assertTrue(error.message!!.contains("'${ContextClass::class.java.name}'"))
292+
assertTrue(error.message!!.contains(".isActive'"))
293+
assertTrue(error.message!!.contains("GraphQLContext"))
294+
}
295+
296+
@Test
297+
fun `data fetcher fails if custom context is only passed as the legacy context object`() {
298+
val options = SchemaParserOptions.newOptions().contextClass(ContextClass::class).build()
299+
val resolver = createFetcher("active", options = options, resolver = object : GraphQLResolver<DataClass> {
300+
fun isActive(dataClass: DataClass, ctx: ContextClass): Boolean {
301+
return true
302+
}
303+
})
304+
305+
assertThrows(ResolverError::class.java) { resolver.get(createEnvironment(DataClass(), legacyContext = ContextClass())) }
306+
}
307+
308+
@Test
309+
fun `data fetcher passes GraphQLContext if it is the custom context class`() {
310+
val context = GraphQLContext.newContext().build()
311+
val options = SchemaParserOptions.newOptions().contextClass(GraphQLContext::class).build()
312+
val resolver = createFetcher("active", options = options, resolver = object : GraphQLResolver<DataClass> {
313+
fun isActive(dataClass: DataClass, ctx: GraphQLContext): Boolean {
314+
return ctx == context
315+
}
316+
})
317+
318+
assertEquals(resolver.get(createEnvironment(DataClass(), context = context)), true)
288319
}
289320

290321
@Test

0 commit comments

Comments
 (0)