Skip to content

Commit bbadaef

Browse files
smyrickdariuszkuc
authored andcommitted
Increase code coverage (ExpediaGroup#331)
Add more unit tests and remove duplicate default values to increase code coverage
1 parent 6f2a466 commit bbadaef

File tree

11 files changed

+264
-39
lines changed

11 files changed

+264
-39
lines changed

graphql-kotlin-federation/src/test/kotlin/com/expediagroup/graphql/federation/execution/ResolversKtTest.kt

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package com.expediagroup.graphql.federation.execution
22

3+
import com.expediagroup.graphql.federation.exception.FederatedRequestFailure
4+
import com.expediagroup.graphql.federation.exception.InvalidFederatedRequest
35
import io.mockk.coEvery
46
import io.mockk.coVerify
7+
import io.mockk.every
58
import io.mockk.mockk
69
import kotlinx.coroutines.runBlocking
710
import org.junit.jupiter.api.Test
@@ -25,4 +28,62 @@ internal class ResolversKtTest {
2528
coVerify(exactly = 1) { mockResolver.resolve(any()) }
2629
}
2730
}
31+
32+
@Test
33+
fun `resolver still works when registry returns null`() {
34+
val indexedValue = mapOf<String, Any>()
35+
val indexedRequests: List<IndexedValue<Map<String, Any>>> = listOf(IndexedValue(7, indexedValue))
36+
val mockResolver: FederatedTypeResolver<*> = mockk()
37+
coEvery { mockResolver.resolve(any()) } returns listOf("foo")
38+
val registry: FederatedTypeRegistry = mockk()
39+
every { registry.getFederatedResolver(any()) } returns null
40+
41+
runBlocking {
42+
val result = resolveType("MyType", indexedRequests, registry)
43+
assertTrue(result.isNotEmpty())
44+
val mappedValue = result.first()
45+
val response = mappedValue.second
46+
assertTrue(response is InvalidFederatedRequest)
47+
coVerify(exactly = 0) { mockResolver.resolve(any()) }
48+
}
49+
}
50+
51+
@Test
52+
fun `resolver maps the value to a failure when the federated resolver throws an exception`() {
53+
val indexedValue = mapOf<String, Any>()
54+
val indexedRequests: List<IndexedValue<Map<String, Any>>> = listOf(IndexedValue(7, indexedValue))
55+
val mockResolver: FederatedTypeResolver<*> = mockk()
56+
coEvery { mockResolver.resolve(any()) } throws Exception("custom exception")
57+
val registry = FederatedTypeRegistry(mapOf("MyType" to mockResolver))
58+
59+
runBlocking {
60+
val result = resolveType("MyType", indexedRequests, registry)
61+
assertTrue(result.isNotEmpty())
62+
val mappedValue = result.first()
63+
val response = mappedValue.second
64+
assertTrue(response is FederatedRequestFailure)
65+
coVerify(exactly = 1) { mockResolver.resolve(any()) }
66+
}
67+
}
68+
69+
@Test
70+
fun `maps to failure if the result size does not match request size`() {
71+
val indexedValue = mapOf<String, Any>()
72+
val indexedRequests: List<IndexedValue<Map<String, Any>>> = listOf(
73+
IndexedValue(7, indexedValue),
74+
IndexedValue(5, indexedValue)
75+
)
76+
val mockResolver: FederatedTypeResolver<*> = mockk()
77+
coEvery { mockResolver.resolve(any()) } returns listOf("foo")
78+
val registry = FederatedTypeRegistry(mapOf("MyType" to mockResolver))
79+
80+
runBlocking {
81+
val result = resolveType("MyType", indexedRequests, registry)
82+
assertEquals(expected = 2, actual = result.size)
83+
val mappedValue = result.first()
84+
val response = mappedValue.second
85+
assertTrue(response is FederatedRequestFailure)
86+
coVerify(exactly = 1) { mockResolver.resolve(any()) }
87+
}
88+
}
2889
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.expediagroup.graphql.directives
2+
3+
import graphql.schema.DataFetcher
4+
import graphql.schema.FieldCoordinates
5+
import graphql.schema.GraphQLCodeRegistry
6+
import graphql.schema.GraphQLDirective
7+
import graphql.schema.GraphQLFieldDefinition
8+
9+
/**
10+
* KotlinFieldDirectiveEnvironment holds wiring information for applying directives on GraphQL fields.
11+
*/
12+
class KotlinFieldDirectiveEnvironment(
13+
field: GraphQLFieldDefinition,
14+
fieldDirective: GraphQLDirective,
15+
private val coordinates: FieldCoordinates,
16+
private val codeRegistry: GraphQLCodeRegistry.Builder
17+
) : KotlinSchemaDirectiveEnvironment<GraphQLFieldDefinition>(element = field, directive = fieldDirective) {
18+
19+
/**
20+
* Retrieve current data fetcher associated with the target element.
21+
*/
22+
fun getDataFetcher(): DataFetcher<Any> = codeRegistry.getDataFetcher(coordinates, element)
23+
24+
/**
25+
* Update target element data fetcher.
26+
*/
27+
fun setDataFetcher(newDataFetcher: DataFetcher<Any>) {
28+
codeRegistry.dataFetcher(coordinates, newDataFetcher)
29+
}
30+
}

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/directives/KotlinSchemaDirectiveEnvironment.kt

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package com.expediagroup.graphql.directives
22

33
import graphql.introspection.Introspection
4-
import graphql.schema.DataFetcher
5-
import graphql.schema.FieldCoordinates
64
import graphql.schema.GraphQLArgument
7-
import graphql.schema.GraphQLCodeRegistry
85
import graphql.schema.GraphQLDirective
96
import graphql.schema.GraphQLDirectiveContainer
107
import graphql.schema.GraphQLEnumType
@@ -43,26 +40,3 @@ open class KotlinSchemaDirectiveEnvironment<out T : GraphQLDirectiveContainer>(
4340
else -> false
4441
}
4542
}
46-
47-
/**
48-
* KotlinFieldDirectiveEnvironment holds wiring information for applying directives on GraphQL fields.
49-
*/
50-
class KotlinFieldDirectiveEnvironment(
51-
field: GraphQLFieldDefinition,
52-
fieldDirective: GraphQLDirective,
53-
private val coordinates: FieldCoordinates,
54-
private val codeRegistry: GraphQLCodeRegistry.Builder
55-
) : KotlinSchemaDirectiveEnvironment<GraphQLFieldDefinition>(element = field, directive = fieldDirective) {
56-
57-
/**
58-
* Retrieve current data fetcher associated with the target element.
59-
*/
60-
fun getDataFetcher(): DataFetcher<Any> = codeRegistry.getDataFetcher(coordinates, element)
61-
62-
/**
63-
* Update target element data fetcher.
64-
*/
65-
fun setDataFetcher(newDataFetcher: DataFetcher<Any>) {
66-
codeRegistry.dataFetcher(coordinates, newDataFetcher)
67-
}
68-
}

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/SchemaGenerator.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ open class SchemaGenerator(val config: SchemaGeneratorConfig) {
9999
open fun enumType(kClass: KClass<out Enum<*>>) =
100100
enumTypeBuilder.enumType(kClass)
101101

102-
open fun scalarType(type: KType, annotatedAsID: Boolean = false) =
102+
open fun scalarType(type: KType, annotatedAsID: Boolean) =
103103
scalarTypeBuilder.scalarType(type, annotatedAsID)
104104

105105
open fun directives(element: KAnnotatedElement, parentClass: KClass<*>? = null): List<GraphQLDirective> =

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/types/FunctionBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import kotlin.reflect.full.isSubclassOf
2121

2222
internal class FunctionBuilder(generator: SchemaGenerator) : TypeBuilder(generator) {
2323

24-
internal fun function(fn: KFunction<*>, parentName: String, target: Any? = null, abstract: Boolean = false): GraphQLFieldDefinition {
24+
internal fun function(fn: KFunction<*>, parentName: String, target: Any?, abstract: Boolean): GraphQLFieldDefinition {
2525
val builder = GraphQLFieldDefinition.newFieldDefinition()
2626
val functionName = fn.getFunctionName()
2727
builder.name(functionName)

graphql-kotlin-schema-generator/src/main/kotlin/com/expediagroup/graphql/generator/types/ScalarBuilder.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import kotlin.reflect.KType
1616

1717
internal class ScalarBuilder(generator: SchemaGenerator) : TypeBuilder(generator) {
1818

19-
internal fun scalarType(type: KType, annotatedAsID: Boolean = false): GraphQLScalarType? {
19+
internal fun scalarType(type: KType, annotatedAsID: Boolean): GraphQLScalarType? {
2020
val kClass = type.getKClass()
2121

2222
val scalar = when {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.expediagroup.graphql.directives
2+
3+
import graphql.schema.DataFetcher
4+
import graphql.schema.FieldCoordinates
5+
import graphql.schema.GraphQLCodeRegistry
6+
import io.mockk.every
7+
import io.mockk.mockk
8+
import io.mockk.verify
9+
import org.junit.jupiter.api.Test
10+
11+
internal class KotlinFieldDirectiveEnvironmentTest {
12+
13+
@Test
14+
fun `getDataFetcher calls the code registry with the coordinates and element`() {
15+
val coordinates: FieldCoordinates = mockk()
16+
val codeRegistry: GraphQLCodeRegistry.Builder = mockk()
17+
every { codeRegistry.getDataFetcher(any<FieldCoordinates>(), any()) } returns mockk()
18+
val environment = KotlinFieldDirectiveEnvironment(mockk(), mockk(), coordinates, codeRegistry)
19+
20+
environment.getDataFetcher()
21+
22+
verify(exactly = 1) { codeRegistry.getDataFetcher(eq(coordinates), any()) }
23+
}
24+
25+
@Test
26+
fun `setDataFetcher sets the new dataFetcher at the coordinates`() {
27+
val coordinates: FieldCoordinates = mockk()
28+
val codeRegistry: GraphQLCodeRegistry.Builder = mockk()
29+
every { codeRegistry.dataFetcher(any(), any<DataFetcher<Any>>()) } returns mockk()
30+
val environment = KotlinFieldDirectiveEnvironment(mockk(), mockk(), coordinates, codeRegistry)
31+
32+
val newDataFetcher: DataFetcher<Any> = mockk()
33+
environment.setDataFetcher(newDataFetcher)
34+
35+
verify(exactly = 1) { codeRegistry.dataFetcher(eq(coordinates), eq(newDataFetcher)) }
36+
}
37+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.expediagroup.graphql.directives
2+
3+
import graphql.introspection.Introspection
4+
import graphql.schema.GraphQLArgument
5+
import graphql.schema.GraphQLDirectiveContainer
6+
import graphql.schema.GraphQLEnumType
7+
import graphql.schema.GraphQLEnumValueDefinition
8+
import graphql.schema.GraphQLFieldDefinition
9+
import graphql.schema.GraphQLInputObjectField
10+
import graphql.schema.GraphQLInputObjectType
11+
import graphql.schema.GraphQLInterfaceType
12+
import graphql.schema.GraphQLObjectType
13+
import graphql.schema.GraphQLScalarType
14+
import graphql.schema.GraphQLUnionType
15+
import io.mockk.mockk
16+
import org.junit.jupiter.api.Test
17+
import kotlin.test.assertFalse
18+
import kotlin.test.assertTrue
19+
20+
internal class KotlinSchemaDirectiveEnvironmentTest {
21+
22+
@Test
23+
fun `isValid checks the directive locations`() {
24+
val directive = graphql.schema.GraphQLDirective.newDirective()
25+
.name("customDirective")
26+
.validLocations(
27+
Introspection.DirectiveLocation.ARGUMENT_DEFINITION,
28+
Introspection.DirectiveLocation.ENUM,
29+
Introspection.DirectiveLocation.ENUM_VALUE,
30+
Introspection.DirectiveLocation.FIELD_DEFINITION,
31+
Introspection.DirectiveLocation.INPUT_FIELD_DEFINITION,
32+
Introspection.DirectiveLocation.INPUT_OBJECT,
33+
Introspection.DirectiveLocation.INTERFACE,
34+
Introspection.DirectiveLocation.OBJECT,
35+
Introspection.DirectiveLocation.SCALAR,
36+
Introspection.DirectiveLocation.UNION
37+
)
38+
.build()
39+
40+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLArgument>(), directive).isValid())
41+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLEnumType>(), directive).isValid())
42+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLEnumValueDefinition>(), directive).isValid())
43+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLFieldDefinition>(), directive).isValid())
44+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLInputObjectField>(), directive).isValid())
45+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLInputObjectType>(), directive).isValid())
46+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLInterfaceType>(), directive).isValid())
47+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLObjectType>(), directive).isValid())
48+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLScalarType>(), directive).isValid())
49+
assertTrue(KotlinSchemaDirectiveEnvironment(mockk<GraphQLUnionType>(), directive).isValid())
50+
}
51+
52+
@Test
53+
fun `isValid returns false in an invalid directive location`() {
54+
val enumDirective = graphql.schema.GraphQLDirective.newDirective()
55+
.name("enumDirective")
56+
.validLocations(Introspection.DirectiveLocation.ENUM)
57+
.build()
58+
assertFalse(KotlinSchemaDirectiveEnvironment(mockk<GraphQLArgument>(), enumDirective).isValid())
59+
}
60+
61+
@Test
62+
fun `isValid returns false on non valid type`() {
63+
assertFalse(KotlinSchemaDirectiveEnvironment(mockk<GraphQLDirectiveContainer>(), mockk()).isValid())
64+
}
65+
}

graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/SchemaGeneratorTest.kt

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ import com.expediagroup.graphql.testSchemaConfig
1313
import com.expediagroup.graphql.toSchema
1414
import graphql.GraphQL
1515
import graphql.Scalars
16+
import graphql.schema.GraphQLFieldDefinition
1617
import graphql.schema.GraphQLNonNull
1718
import graphql.schema.GraphQLObjectType
19+
import graphql.schema.GraphQLSchema
1820
import org.junit.jupiter.api.Test
1921
import java.net.CookieManager
2022
import java.util.UUID
@@ -44,6 +46,53 @@ class SchemaGeneratorTest {
4446
assertEquals(1, geo?.get("query")?.get("id"))
4547
}
4648

49+
@Test
50+
fun `SchemaGenerator generates a simple GraphQL schema with default builder`() {
51+
val schemaGenerator = SchemaGenerator(testSchemaConfig)
52+
val schema = schemaGenerator.generate(
53+
queries = listOf(TopLevelObject(QueryObject())),
54+
mutations = listOf(TopLevelObject(MutationObject())),
55+
subscriptions = emptyList()
56+
)
57+
58+
val graphQL = GraphQL.newGraphQL(schema).build()
59+
60+
val result = graphQL.execute(" { query(value: 1) { id } }")
61+
val geo: Map<String, Map<String, Any>>? = result.getData()
62+
63+
assertEquals(1, geo?.get("query")?.get("id"))
64+
}
65+
66+
@Test
67+
fun `SchemaGenerator generates a simple GraphQL schema with predefined builder`() {
68+
val schemaGenerator = SchemaGenerator(testSchemaConfig)
69+
val field = GraphQLFieldDefinition.newFieldDefinition()
70+
.name("foo")
71+
.type(Scalars.GraphQLInt)
72+
.build()
73+
val customObject = GraphQLObjectType.Builder()
74+
.field(field)
75+
.name("MyObject")
76+
.build()
77+
val builder = GraphQLSchema.newSchema()
78+
.additionalType(customObject)
79+
80+
val schema = schemaGenerator.generate(
81+
queries = listOf(TopLevelObject(QueryObject())),
82+
mutations = listOf(TopLevelObject(MutationObject())),
83+
subscriptions = emptyList(),
84+
builder = builder
85+
)
86+
87+
val graphQL = GraphQL.newGraphQL(schema).build()
88+
89+
val result = graphQL.execute(" { query(value: 1) { id } }")
90+
val geo: Map<String, Map<String, Any>>? = result.getData()
91+
92+
assertEquals(1, geo?.get("query")?.get("id"))
93+
assertNotNull(schema.getType("MyObject"))
94+
}
95+
4796
@Test
4897
fun `Schema generator exposes arrays of primitive types as function arguments`() {
4998
val schema = toSchema(queries = listOf(TopLevelObject(QueryWithArray())), config = testSchemaConfig)

graphql-kotlin-schema-generator/src/test/kotlin/com/expediagroup/graphql/generator/extensions/GraphQLExtensionsTest.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,15 @@ internal class GraphQLExtensionsTest {
111111
assertEquals(expected = 3, actual = container.getAllDirectives().size)
112112
}
113113

114+
@Test
115+
fun `safeCast with GraphQLType passes`() {
116+
val type: GraphQLType = mockk()
117+
every { type.name } returns "foo"
118+
119+
val castedType = type.safeCast<GraphQLType>()
120+
assertEquals("foo", castedType.name)
121+
}
122+
114123
@Test
115124
fun `safeCast valid type passes`() {
116125
val type: GraphQLType = GraphQLInterfaceType.newInterface().name("name").description("description").build()

0 commit comments

Comments
 (0)