Skip to content

Commit 7f012f2

Browse files
committed
Add GraphQlClient and GraphQlTester Kotlin extensions
This commit adds Kotlin extensions for `GraphQlClient` and `GraphQlTester`. Developers can now use dedicated inline functions with reified generics instead of using `Class<?>` or `ParameterizedTypeReference` arguments for expressing the expected return type. Closes gh-1331
1 parent f0cd68c commit 7f012f2

File tree

7 files changed

+258
-0
lines changed

7 files changed

+258
-0
lines changed

platform/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ dependencies {
4444
api("org.awaitility:awaitility:4.3.0")
4545
api("com.squareup.okhttp3:mockwebserver3:5.1.0")
4646
api("org.hamcrest:hamcrest:3.0")
47+
api("io.mockk:mockk:1.14.5")
4748

4849
api("com.h2database:h2:2.3.232")
4950
api("org.hibernate.orm:hibernate-core:7.1.0.Final")

spring-graphql-test/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
description = "Spring Support for Testing GraphQL Applications"
22

3+
apply plugin: "kotlin"
4+
35
dependencies {
46
api project(':spring-graphql')
57
api 'com.graphql-java:graphql-java'
@@ -27,6 +29,7 @@ dependencies {
2729
testImplementation 'org.junit.jupiter:junit-jupiter'
2830
testImplementation 'org.assertj:assertj-core'
2931
testImplementation 'org.mockito:mockito-core'
32+
testImplementation 'io.mockk:mockk'
3033
testImplementation 'org.skyscreamer:jsonassert'
3134
testImplementation 'org.springframework:spring-messaging'
3235
testImplementation 'org.springframework:spring-webflux'
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright 2025-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.graphql.test.tester
18+
19+
import org.springframework.core.ParameterizedTypeReference
20+
21+
/**
22+
* Extension for [GraphQlTester.Path.entity] providing a `entity<Book>()` variant
23+
* leveraging Kotlin reified type parameters. This extension is not subject to type
24+
* erasure and retains actual generic type arguments.
25+
*
26+
* @author Brian Clozel
27+
* @since 2.0
28+
*/
29+
inline fun <reified T : Any> GraphQlTester.Path.entity(): GraphQlTester.Entity<T, *> =
30+
entity(object : ParameterizedTypeReference<T>() {})
31+
32+
/**
33+
* Extension for [GraphQlTester.Path.entityList] providing a `entityList<Book>()` variant
34+
* leveraging Kotlin reified type parameters. This extension is not subject to type
35+
* erasure and retains actual generic type arguments.
36+
*
37+
* @author Brian Clozel
38+
* @since 2.0
39+
*/
40+
inline fun <reified T : Any> GraphQlTester.Path.entityList(): GraphQlTester.EntityList<T> =
41+
entityList(object : ParameterizedTypeReference<T>() {})
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright 2025-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.graphql.test.tester
18+
19+
import io.mockk.mockk
20+
import io.mockk.verify
21+
import org.junit.jupiter.api.Test
22+
import org.springframework.core.ParameterizedTypeReference
23+
24+
/**
25+
* Tests for [GraphQlTester] Kotlin extensions.
26+
*
27+
* @author Brian Clozel
28+
*/
29+
class GraphQlTesterExtensionsTests {
30+
31+
private val testerPath = mockk<GraphQlTester.Path>(relaxed = true)
32+
33+
@Test
34+
fun `Path#entity with reified type parameters`() {
35+
testerPath.entity<Map<String, Book>>()
36+
verify { testerPath.entity(object : ParameterizedTypeReference<Map<String, Book>>() {}) }
37+
}
38+
39+
@Test
40+
fun `Path#entityList with reified type parameters`() {
41+
testerPath.entityList<Map<String, Book>>()
42+
verify { testerPath.entityList(object : ParameterizedTypeReference<Map<String, Book>>() {}) }
43+
}
44+
45+
private class Book {}
46+
47+
}

spring-graphql/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ dependencies {
5757
testImplementation 'org.junit.jupiter:junit-jupiter'
5858
testImplementation 'org.assertj:assertj-core'
5959
testImplementation 'org.mockito:mockito-core'
60+
testImplementation 'io.mockk:mockk'
6061
testImplementation 'org.awaitility:awaitility'
6162
testImplementation 'io.projectreactor:reactor-test'
6263
testImplementation "org.jetbrains.kotlin:kotlin-reflect"
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright 2025-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.graphql.client
18+
19+
import org.springframework.core.ParameterizedTypeReference
20+
import reactor.core.publisher.Flux
21+
import reactor.core.publisher.Mono
22+
23+
/**
24+
* Extension for [GraphQlClient.RetrieveSpec.toEntity] providing a `toEntity<Book>()` variant
25+
* leveraging Kotlin reified type parameters. This extension is not subject to type
26+
* erasure and retains actual generic type arguments.
27+
*
28+
* @author Brian Clozel
29+
* @since 2.0
30+
*/
31+
inline fun <reified T : Any> GraphQlClient.RetrieveSpec.toEntity(): Mono<T> =
32+
toEntity(object : ParameterizedTypeReference<T>() {})
33+
34+
/**
35+
* Extension for [GraphQlClient.RetrieveSpec.toEntityList] providing a `toEntityList<Book>()` variant
36+
* leveraging Kotlin reified type parameters. This extension is not subject to type
37+
* erasure and retains actual generic type arguments.
38+
*
39+
* @author Brian Clozel
40+
* @since 2.0
41+
*/
42+
inline fun <reified T : Any> GraphQlClient.RetrieveSpec.toEntityList(): Mono<List<T>> =
43+
toEntityList(object : ParameterizedTypeReference<T>() {})
44+
45+
/**
46+
* Extension for [GraphQlClient.RetrieveSyncSpec.toEntity] providing a `toEntity<Book>()` variant
47+
* leveraging Kotlin reified type parameters. This extension is not subject to type
48+
* erasure and retains actual generic type arguments.
49+
*
50+
* @author Brian Clozel
51+
* @since 2.0
52+
*/
53+
inline fun <reified T : Any> GraphQlClient.RetrieveSyncSpec.toEntity(): T? =
54+
toEntity(object : ParameterizedTypeReference<T>() {})
55+
56+
/**
57+
* Extension for [GraphQlClient.RetrieveSyncSpec.toEntityList] providing a `toEntityList<Book>()` variant
58+
* leveraging Kotlin reified type parameters. This extension is not subject to type
59+
* erasure and retains actual generic type arguments.
60+
*
61+
* @author Brian Clozel
62+
* @since 2.0
63+
*/
64+
inline fun <reified T : Any> GraphQlClient.RetrieveSyncSpec.toEntityList(): List<T> =
65+
toEntityList(object : ParameterizedTypeReference<T>() {})
66+
67+
/**
68+
* Extension for [GraphQlClient.RetrieveSubscriptionSpec.toEntity] providing a `toEntity<Book>()` variant
69+
* leveraging Kotlin reified type parameters. This extension is not subject to type
70+
* erasure and retains actual generic type arguments.
71+
*
72+
* @author Brian Clozel
73+
* @since 2.0
74+
*/
75+
inline fun <reified T : Any> GraphQlClient.RetrieveSubscriptionSpec.toEntity(): Flux<T> =
76+
toEntity(object : ParameterizedTypeReference<T>() {})
77+
78+
/**
79+
* Extension for [GraphQlClient.RetrieveSubscriptionSpec.toEntityList] providing a `toEntityList<Book>()` variant
80+
* leveraging Kotlin reified type parameters. This extension is not subject to type
81+
* erasure and retains actual generic type arguments.
82+
*
83+
* @author Brian Clozel
84+
* @since 2.0
85+
*/
86+
inline fun <reified T : Any> GraphQlClient.RetrieveSubscriptionSpec.toEntityList(): Flux<List<T>> =
87+
toEntityList(object : ParameterizedTypeReference<T>() {})
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2025-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.graphql.client
18+
19+
import io.mockk.mockk
20+
import io.mockk.verify
21+
import org.junit.jupiter.api.Test
22+
import org.springframework.core.ParameterizedTypeReference
23+
24+
25+
/**
26+
* Tests for [GraphQlClient] Kotlin extensions.
27+
*
28+
* @author Brian Clozel
29+
*/
30+
class GraphQlClientExtensionsTests {
31+
32+
private val retrieveSpec = mockk<GraphQlClient.RetrieveSpec>(relaxed = true)
33+
34+
private val retrieveSyncSpec = mockk<GraphQlClient.RetrieveSyncSpec>(relaxed = true)
35+
36+
private val retrieveSubscriptionSpec = mockk<GraphQlClient.RetrieveSubscriptionSpec>(relaxed = true)
37+
38+
39+
@Test
40+
fun `RetrieveSpec#toEntity with reified type parameters`() {
41+
retrieveSpec.toEntity<Map<String, Book>>()
42+
verify { retrieveSpec.toEntity(object : ParameterizedTypeReference<Map<String, Book>>() {}) }
43+
}
44+
45+
@Test
46+
fun `RetrieveSpec#toEntityList with reified type parameters`() {
47+
retrieveSpec.toEntityList<Book>()
48+
verify { retrieveSpec.toEntityList(object : ParameterizedTypeReference<Book>() {}) }
49+
}
50+
51+
@Test
52+
fun `RetrieveSyncSpec#toEntity with reified type parameters`() {
53+
retrieveSyncSpec.toEntity<Map<String, Book>>()
54+
verify { retrieveSyncSpec.toEntity(object : ParameterizedTypeReference<Map<String, Book>>() {}) }
55+
}
56+
57+
@Test
58+
fun `RetrieveSyncSpec#toEntityList with reified type parameters`() {
59+
retrieveSyncSpec.toEntityList<Book>()
60+
verify { retrieveSyncSpec.toEntityList(object : ParameterizedTypeReference<Book>() {}) }
61+
}
62+
63+
@Test
64+
fun `RetrieveSubscriptionSpec#toEntity with reified type parameters`() {
65+
retrieveSubscriptionSpec.toEntity<Map<String, Book>>()
66+
verify { retrieveSubscriptionSpec.toEntity(object : ParameterizedTypeReference<Map<String, Book>>() {}) }
67+
}
68+
69+
@Test
70+
fun `RetrieveSubscriptionSpec#toEntityList with reified type parameters`() {
71+
retrieveSubscriptionSpec.toEntityList<Book>()
72+
verify { retrieveSubscriptionSpec.toEntityList(object : ParameterizedTypeReference<Book>() {}) }
73+
}
74+
75+
76+
private class Book
77+
78+
}

0 commit comments

Comments
 (0)