Skip to content

Commit 81d6afe

Browse files
committed
Merge pull request #11604 from sdeleuze:test-rest-template-improvements
* pr/11604: Improve Kotlin extensions doc about type erasure
2 parents b7a9933 + d4c91d2 commit 81d6afe

File tree

2 files changed

+123
-50
lines changed

2 files changed

+123
-50
lines changed

spring-boot-project/spring-boot-test/src/main/kotlin/org/springframework/boot/test/web/client/TestRestTemplateExtensions.kt

+93-50
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ import org.springframework.web.client.RestClientException
2525
import java.net.URI
2626

2727
/**
28-
* Extension for [TestRestTemplate.getForObject] avoiding specifying the type
29-
* parameter thanks to Kotlin reified type parameters.
28+
* Extension for [TestRestTemplate.getForObject] providing a `getForObject<Foo>(...)`
29+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
30+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
31+
* generic type arguments.
3032
*
3133
* @author Sebastien Deleuze
3234
* @since 2.0.0
@@ -36,8 +38,10 @@ inline fun <reified T : Any> TestRestTemplate.getForObject(url: String, vararg u
3638
getForObject(url, T::class.java, *uriVariables)
3739

3840
/**
39-
* Extension for [TestRestTemplate.getForObject] avoiding specifying the type
40-
* parameter thanks to Kotlin reified type parameters.
41+
* Extension for [TestRestTemplate.getForObject] providing a `getForObject<Foo>(...)`
42+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
43+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
44+
* generic type arguments.
4145
*
4246
* @author Sebastien Deleuze
4347
* @since 2.0.0
@@ -47,8 +51,10 @@ inline fun <reified T : Any> TestRestTemplate.getForObject(url: String, uriVaria
4751
getForObject(url, T::class.java, uriVariables)
4852

4953
/**
50-
* Extension for [TestRestTemplate.getForObject] avoiding specifying the type parameter
51-
* thanks to Kotlin reified type parameters.
54+
* Extension for [TestRestTemplate.getForObject] providing a `getForObject<Foo>(...)`
55+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
56+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
57+
* generic type arguments.
5258
*
5359
* @author Sebastien Deleuze
5460
* @since 2.0.0
@@ -58,8 +64,10 @@ inline fun <reified T : Any> TestRestTemplate.getForObject(url: URI): T? =
5864
getForObject(url, T::class.java)
5965

6066
/**
61-
* Extension for [TestRestTemplate.getForEntity] avoiding requiring the type parameter
62-
* thanks to Kotlin reified type parameters.
67+
* Extension for [TestRestTemplate.getForEntity] providing a `getForEntity<Foo>(...)`
68+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
69+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
70+
* generic type arguments.
6371
*
6472
* @author Sebastien Deleuze
6573
* @since 2.0.0
@@ -69,8 +77,10 @@ inline fun <reified T : Any> TestRestTemplate.getForEntity(url: URI): ResponseEn
6977
getForEntity(url, T::class.java)
7078

7179
/**
72-
* Extension for [TestRestTemplate.getForEntity] avoiding requiring the type parameter
73-
* thanks to Kotlin reified type parameters.
80+
* Extension for [TestRestTemplate.getForEntity] providing a `getForEntity<Foo>(...)`
81+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
82+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
83+
* generic type arguments.
7484
*
7585
* @author Sebastien Deleuze
7686
* @since 2.0.0
@@ -80,8 +90,10 @@ inline fun <reified T : Any> TestRestTemplate.getForEntity(url: String, vararg u
8090
getForEntity(url, T::class.java, *uriVariables)
8191

8292
/**
83-
* Extension for [TestRestTemplate.getForEntity] avoiding requiring the type parameter
84-
* thanks to Kotlin reified type parameters.
93+
* Extension for [TestRestTemplate.getForEntity] providing a `getForEntity<Foo>(...)`
94+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
95+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
96+
* generic type arguments.
8597
*
8698
* @author Sebastien Deleuze
8799
* @since 2.0.0
@@ -91,140 +103,171 @@ inline fun <reified T : Any> TestRestTemplate.getForEntity(url: String, uriVaria
91103
getForEntity(url, T::class.java, uriVariables)
92104

93105
/**
94-
* Extension for [TestRestTemplate.patchForObject] avoiding specifying the type parameter
95-
* thanks to Kotlin reified type parameters.
106+
* Extension for [TestRestTemplate.patchForObject] providing a `patchForObject<Foo>(...)`
107+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
108+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
109+
* generic type arguments.
96110
*
97111
* @author Sebastien Deleuze
98112
* @since 2.0.0
99113
*/
100114
@Throws(RestClientException::class)
101-
inline fun <reified T : Any> TestRestTemplate.patchForObject(url: String, request: Any, vararg uriVariables: Any): T? =
115+
inline fun <reified T : Any> TestRestTemplate.patchForObject(url: String, request: Any? = null,
116+
vararg uriVariables: Any): T? =
102117
patchForObject(url, request, T::class.java, *uriVariables)
103118

104119
/**
105-
* Extension for [TestRestTemplate.patchForObject] avoiding specifying the type parameter
106-
* thanks to Kotlin reified type parameters.
120+
* Extension for [TestRestTemplate.patchForObject] providing a `patchForObject<Foo>(...)`
121+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
122+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
123+
* generic type arguments.
107124
*
108125
* @author Sebastien Deleuze
109126
* @since 2.0.0
110127
*/
111128
@Throws(RestClientException::class)
112-
inline fun <reified T : Any> TestRestTemplate.patchForObject(url: String, request: Any, uriVariables: Map<String, *>): T? =
129+
inline fun <reified T : Any> TestRestTemplate.patchForObject(url: String, request: Any? = null,
130+
uriVariables: Map<String, *>): T? =
113131
patchForObject(url, request, T::class.java, uriVariables)
114132

115133
/**
116-
* Extension for [TestRestTemplate.patchForObject] avoiding specifying the type parameter
117-
* thanks to Kotlin reified type parameters.
134+
* Extension for [TestRestTemplate.patchForObject] providing a `patchForObject<Foo>(...)`
135+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
136+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
137+
* generic type arguments.
118138
*
119139
* @author Sebastien Deleuze
120140
* @since 2.0.0
121141
*/
122142
@Throws(RestClientException::class)
123-
inline fun <reified T : Any> TestRestTemplate.patchForObject(url: URI, request: Any): T? =
143+
inline fun <reified T : Any> TestRestTemplate.patchForObject(url: URI, request: Any? = null): T? =
124144
patchForObject(url, request, T::class.java)
125145

126146
/**
127-
* Extension for [TestRestTemplate.postForObject] avoiding specifying the type parameter
128-
* thanks to Kotlin reified type parameters.
147+
* Extension for [TestRestTemplate.postForObject] providing a `postForObject<Foo>(...)`
148+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
149+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
150+
* generic type arguments.
129151
*
130152
* @author Sebastien Deleuze
131153
* @since 2.0.0
132154
*/
133155
@Throws(RestClientException::class)
134-
inline fun <reified T : Any> TestRestTemplate.postForObject(url: String, request: Any, vararg uriVariables: Any): T? =
156+
inline fun <reified T : Any> TestRestTemplate.postForObject(url: String, request: Any? = null,
157+
vararg uriVariables: Any): T? =
135158
postForObject(url, request, T::class.java, *uriVariables)
136159

137160
/**
138-
* Extension for [TestRestTemplate.postForObject] avoiding specifying the type parameter
139-
* thanks to Kotlin reified type parameters.
161+
* Extension for [TestRestTemplate.postForObject] providing a `postForObject<Foo>(...)`
162+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
163+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
164+
* generic type arguments.
140165
*
141166
* @author Sebastien Deleuze
142167
* @since 2.0.0
143168
*/
144169
@Throws(RestClientException::class)
145-
inline fun <reified T : Any> TestRestTemplate.postForObject(url: String, request: Any, uriVariables: Map<String, *>): T? =
170+
inline fun <reified T : Any> TestRestTemplate.postForObject(url: String, request: Any? = null,
171+
uriVariables: Map<String, *>): T? =
146172
postForObject(url, request, T::class.java, uriVariables)
147173

148174
/**
149-
* Extension for [TestRestTemplate.postForObject] avoiding specifying the type parameter
150-
* thanks to Kotlin reified type parameters.
175+
* Extension for [TestRestTemplate.postForObject] providing a `postForObject<Foo>(...)`
176+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
177+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
178+
* generic type arguments.
151179
*
152180
* @author Sebastien Deleuze
153181
* @since 2.0.0
154182
*/
155183
@Throws(RestClientException::class)
156-
inline fun <reified T : Any> TestRestTemplate.postForObject(url: URI, request: Any): T? =
184+
inline fun <reified T : Any> TestRestTemplate.postForObject(url: URI, request: Any? = null): T? =
157185
postForObject(url, request, T::class.java)
158186

159187
/**
160-
* Extension for [TestRestTemplate.postForEntity] avoiding specifying the type parameter
161-
* thanks to Kotlin reified type parameters.
188+
* Extension for [TestRestTemplate.postForEntity] providing a `postForEntity<Foo>(...)`
189+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
190+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
191+
* generic type arguments.
162192
*
163193
* @author Sebastien Deleuze
164194
* @since 2.0.0
165195
*/
166196
@Throws(RestClientException::class)
167-
inline fun <reified T : Any> TestRestTemplate.postForEntity(url: String, request: Any, vararg uriVariables: Any): ResponseEntity<T> =
197+
inline fun <reified T : Any> TestRestTemplate.postForEntity(url: String, request: Any? = null,
198+
vararg uriVariables: Any): ResponseEntity<T> =
168199
postForEntity(url, request, T::class.java, *uriVariables)
169200

170201
/**
171-
* Extension for [TestRestTemplate.postForEntity] avoiding specifying the type parameter
172-
* thanks to Kotlin reified type parameters.
202+
* Extension for [TestRestTemplate.postForEntity] providing a `postForEntity<Foo>(...)`
203+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
204+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
205+
* generic type arguments.
173206
*
174207
* @author Sebastien Deleuze
175208
* @since 2.0.0
176209
*/
177210
@Throws(RestClientException::class)
178-
inline fun <reified T : Any> TestRestTemplate.postForEntity(url: String, request: Any, uriVariables: Map<String, *>): ResponseEntity<T> =
211+
inline fun <reified T : Any> TestRestTemplate.postForEntity(url: String, request: Any? = null,
212+
uriVariables: Map<String, *>): ResponseEntity<T> =
179213
postForEntity(url, request, T::class.java, uriVariables)
180214

181215
/**
182-
* Extension for [TestRestTemplate.postForEntity] avoiding specifying the type parameter
183-
* thanks to Kotlin reified type parameters.
216+
* Extension for [TestRestTemplate.postForEntity] providing a `postForEntity<Foo>(...)`
217+
* variant leveraging Kotlin reified type parameters. Like the original Java method, this
218+
* extension is subject to type erasure. Use [exchange] if you need to retain actual
219+
* generic type arguments.
184220
*
185221
* @author Sebastien Deleuze
186222
* @since 2.0.0
187223
*/
188224
@Throws(RestClientException::class)
189-
inline fun <reified T : Any> TestRestTemplate.postForEntity(url: URI, request: Any): ResponseEntity<T> =
225+
inline fun <reified T : Any> TestRestTemplate.postForEntity(url: URI, request: Any? = null): ResponseEntity<T> =
190226
postForEntity(url, request, T::class.java)
191227

192228
/**
193-
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter
194-
* thanks to Kotlin reified type parameters.
229+
* Extension for [TestRestTemplate.exchange] providing an `exchange<Foo>(...)`
230+
* variant leveraging Kotlin reified type parameters. This extension is not subject to
231+
* type erasure and retains actual generic type arguments.
195232
*
196233
* @author Sebastien Deleuze
197234
* @since 2.0.0
198235
*/
199236
@Throws(RestClientException::class)
200-
inline fun <reified T : Any> TestRestTemplate.exchange(url: String, method: HttpMethod, requestEntity: HttpEntity<*>, vararg uriVariables: Any): ResponseEntity<T> =
237+
inline fun <reified T : Any> TestRestTemplate.exchange(url: String, method: HttpMethod,
238+
requestEntity: HttpEntity<*>? = null, vararg uriVariables: Any): ResponseEntity<T> =
201239
exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}, *uriVariables)
202240

203241
/**
204-
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter
205-
* thanks to Kotlin reified type parameters.
242+
* Extension for [TestRestTemplate.exchange] providing an `exchange<Foo>(...)`
243+
* variant leveraging Kotlin reified type parameters. This extension is not subject to
244+
* type erasure and retains actual generic type arguments.
206245
*
207246
* @author Sebastien Deleuze
208247
* @since 2.0.0
209248
*/
210249
@Throws(RestClientException::class)
211-
inline fun <reified T : Any> TestRestTemplate.exchange(url: String, method: HttpMethod, requestEntity: HttpEntity<*>, uriVariables: Map<String, *>): ResponseEntity<T> =
250+
inline fun <reified T : Any> TestRestTemplate.exchange(url: String, method: HttpMethod,
251+
requestEntity: HttpEntity<*>? = null, uriVariables: Map<String, *>): ResponseEntity<T> =
212252
exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}, uriVariables)
213253

214254
/**
215-
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter
216-
* thanks to Kotlin reified type parameters.
255+
* Extension for [TestRestTemplate.exchange] providing an `exchange<Foo>(...)`
256+
* variant leveraging Kotlin reified type parameters. This extension is not subject to
257+
* type erasure and retains actual generic type arguments.
217258
*
218259
* @author Sebastien Deleuze
219260
* @since 2.0.0
220261
*/
221262
@Throws(RestClientException::class)
222-
inline fun <reified T : Any> TestRestTemplate.exchange(url: URI, method: HttpMethod, requestEntity: HttpEntity<*>): ResponseEntity<T> =
263+
inline fun <reified T : Any> TestRestTemplate.exchange(url: URI, method: HttpMethod,
264+
requestEntity: HttpEntity<*>? = null): ResponseEntity<T> =
223265
exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {})
224266

225267
/**
226-
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter
227-
* thanks to Kotlin reified type parameters.
268+
* Extension for [TestRestTemplate.exchange] providing an `exchange<Foo>(...)`
269+
* variant leveraging Kotlin reified type parameters. This extension is not subject to
270+
* type erasure and retains actual generic type arguments.
228271
*
229272
* @author Sebastien Deleuze
230273
* @since 2.0.0

spring-boot-project/spring-boot-test/src/test/kotlin/org/springframework/boot/test/web/client/TestRestTemplateExtensionsTests.kt

+30
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,13 @@ class TestRestTemplateExtensionsTests {
122122
verify(template, times(1)).patchForObject(url, body, Foo::class.java)
123123
}
124124

125+
@Test
126+
fun `patchForObject with reified type parameters`() {
127+
val url = "https://spring.io"
128+
template.patchForObject<Foo>(url)
129+
verify(template, times(1)).patchForObject(url, null, Foo::class.java)
130+
}
131+
125132
@Test
126133
fun `postForObject with reified type parameters, String, Any and varargs`() {
127134
val url = "https://spring.io"
@@ -149,6 +156,13 @@ class TestRestTemplateExtensionsTests {
149156
verify(template, times(1)).postForObject(url, body, Foo::class.java)
150157
}
151158

159+
@Test
160+
fun `postForObject with reified type parameters`() {
161+
val url = "https://spring.io"
162+
template.postForObject<Foo>(url)
163+
verify(template, times(1)).postForObject(url, null, Foo::class.java)
164+
}
165+
152166
@Test
153167
fun `postForEntity with reified type parameters, String, Any and varargs`() {
154168
val url = "https://spring.io"
@@ -176,6 +190,13 @@ class TestRestTemplateExtensionsTests {
176190
verify(template, times(1)).postForEntity(url, body, Foo::class.java)
177191
}
178192

193+
@Test
194+
fun `postForEntity with reified type parameters`() {
195+
val url = "https://spring.io"
196+
template.postForEntity<Foo>(url)
197+
verify(template, times(1)).postForEntity(url, null, Foo::class.java)
198+
}
199+
179200
@Test
180201
fun `exchange with reified type parameters, String, HttpMethod, HttpEntity and varargs`() {
181202
val url = "https://spring.io"
@@ -217,6 +238,15 @@ class TestRestTemplateExtensionsTests {
217238
object : ParameterizedTypeReference<List<Foo>>() {})
218239
}
219240

241+
@Test
242+
fun `exchange with reified type parameters, String and HttpMethod`() {
243+
val url = "https://spring.io"
244+
val method = HttpMethod.GET
245+
template.exchange<List<Foo>>(url, method)
246+
verify(template, times(1)).exchange(url, method, null,
247+
object : ParameterizedTypeReference<List<Foo>>() {})
248+
}
249+
220250
@Test
221251
fun `RestOperations are available`() {
222252
val extensions = Class.forName(

0 commit comments

Comments
 (0)