Browse Source
This commit introduces Kotlin extensions similar to the RestOperations ones in order to be able to take advantage of Kotlin reified type parameters for example. See gh-11039pull/11135/merge
4 changed files with 560 additions and 0 deletions
@ -0,0 +1,234 @@
@@ -0,0 +1,234 @@
|
||||
/* |
||||
* Copyright 2012-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.test.web.client |
||||
|
||||
import org.springframework.core.ParameterizedTypeReference |
||||
import org.springframework.http.HttpEntity |
||||
import org.springframework.http.HttpMethod |
||||
import org.springframework.http.RequestEntity |
||||
import org.springframework.http.ResponseEntity |
||||
import org.springframework.web.client.RestClientException |
||||
import java.net.URI |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.getForObject] avoiding specifying the type |
||||
* parameter thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.getForObject(url: String, vararg uriVariables: Any): T? = |
||||
getForObject(url, T::class.java, *uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.getForObject] avoiding specifying the type |
||||
* parameter thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.getForObject(url: String, uriVariables: Map<String, Any?>): T? = |
||||
getForObject(url, T::class.java, uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.getForObject] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.getForObject(url: URI): T? = |
||||
getForObject(url, T::class.java) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.getForEntity] avoiding requiring the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.getForEntity(url: URI): ResponseEntity<T> = |
||||
getForEntity(url, T::class.java) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.getForEntity] avoiding requiring the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.getForEntity(url: String, vararg uriVariables: Any): ResponseEntity<T> = |
||||
getForEntity(url, T::class.java, *uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.getForEntity] avoiding requiring the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.getForEntity(url: String, uriVariables: Map<String, *>): ResponseEntity<T> = |
||||
getForEntity(url, T::class.java, uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.patchForObject] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.patchForObject(url: String, request: Any, vararg uriVariables: Any): T? = |
||||
patchForObject(url, request, T::class.java, *uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.patchForObject] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.patchForObject(url: String, request: Any, uriVariables: Map<String, *>): T? = |
||||
patchForObject(url, request, T::class.java, uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.patchForObject] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.patchForObject(url: URI, request: Any): T? = |
||||
patchForObject(url, request, T::class.java) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.postForObject] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.postForObject(url: String, request: Any, vararg uriVariables: Any): T? = |
||||
postForObject(url, request, T::class.java, *uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.postForObject] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.postForObject(url: String, request: Any, uriVariables: Map<String, *>): T? = |
||||
postForObject(url, request, T::class.java, uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.postForObject] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.postForObject(url: URI, request: Any): T? = |
||||
postForObject(url, request, T::class.java) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.postForEntity] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.postForEntity(url: String, request: Any, vararg uriVariables: Any): ResponseEntity<T> = |
||||
postForEntity(url, request, T::class.java, *uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.postForEntity] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.postForEntity(url: String, request: Any, uriVariables: Map<String, *>): ResponseEntity<T> = |
||||
postForEntity(url, request, T::class.java, uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.postForEntity] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.postForEntity(url: URI, request: Any): ResponseEntity<T> = |
||||
postForEntity(url, request, T::class.java) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.exchange(url: String, method: HttpMethod, requestEntity: HttpEntity<*>, vararg uriVariables: Any): ResponseEntity<T> = |
||||
exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}, *uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.exchange(url: String, method: HttpMethod, requestEntity: HttpEntity<*>, uriVariables: Map<String, *>): ResponseEntity<T> = |
||||
exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}, uriVariables) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.exchange(url: URI, method: HttpMethod, requestEntity: HttpEntity<*>): ResponseEntity<T> = |
||||
exchange(url, method, requestEntity, object : ParameterizedTypeReference<T>() {}) |
||||
|
||||
/** |
||||
* Extension for [TestRestTemplate.exchange] avoiding specifying the type parameter |
||||
* thanks to Kotlin reified type parameters. |
||||
* |
||||
* @author Sebastien Deleuze |
||||
* @since 2.0.0 |
||||
*/ |
||||
@Throws(RestClientException::class) |
||||
inline fun <reified T: Any> TestRestTemplate.exchange(requestEntity: RequestEntity<*>): ResponseEntity<T> = |
||||
exchange(requestEntity, object : ParameterizedTypeReference<T>() {}) |
||||
@ -0,0 +1,232 @@
@@ -0,0 +1,232 @@
|
||||
/* |
||||
* Copyright 2012-2017 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0 |
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.boot.test.web.client |
||||
|
||||
import com.nhaarman.mockito_kotlin.mock |
||||
import org.junit.Assert |
||||
import org.junit.Test |
||||
import org.junit.runner.RunWith |
||||
import org.mockito.Answers |
||||
import org.mockito.Mock |
||||
import org.mockito.Mockito.* |
||||
import org.mockito.junit.MockitoJUnitRunner |
||||
import org.springframework.core.ParameterizedTypeReference |
||||
import org.springframework.http.HttpEntity |
||||
import org.springframework.http.HttpMethod |
||||
import org.springframework.http.RequestEntity |
||||
import org.springframework.util.ReflectionUtils |
||||
import org.springframework.web.client.RestOperations |
||||
import java.net.URI |
||||
import kotlin.reflect.full.createType |
||||
import kotlin.reflect.jvm.kotlinFunction |
||||
|
||||
/** |
||||
* Mock object based tests for [TestRestTemplate] Kotlin extensions |
||||
* |
||||
* @author Sebastien Deleuze |
||||
*/ |
||||
@RunWith(MockitoJUnitRunner::class) |
||||
class TestRestTemplateExtensionsTests { |
||||
|
||||
@Mock(answer = Answers.RETURNS_MOCKS) |
||||
lateinit var template: TestRestTemplate |
||||
|
||||
@Test |
||||
fun `getForObject with reified type parameters, String and varargs`() { |
||||
val url = "https://spring.io" |
||||
val var1 = "var1" |
||||
val var2 = "var2" |
||||
template.getForObject<Foo>(url, var1, var2) |
||||
template.restTemplate |
||||
verify(template, times(1)).getForObject(url, Foo::class.java, var1, var2) |
||||
} |
||||
|
||||
@Test |
||||
fun `getForObject with reified type parameters, String and Map`() { |
||||
val url = "https://spring.io" |
||||
val vars = mapOf(Pair("key1", "value1"), Pair("key2", "value2")) |
||||
template.getForObject<Foo>(url, vars) |
||||
verify(template, times(1)).getForObject(url, Foo::class.java, vars) |
||||
} |
||||
|
||||
@Test |
||||
fun `getForObject with reified type parameters and URI`() { |
||||
val url = URI("https://spring.io") |
||||
template.getForObject<Foo>(url) |
||||
verify(template, times(1)).getForObject(url, Foo::class.java) |
||||
} |
||||
|
||||
@Test |
||||
fun `getForEntity with reified type parameters, String and URI`() { |
||||
val url = URI("https://spring.io") |
||||
template.getForEntity<Foo>(url) |
||||
verify(template, times(1)).getForEntity(url, Foo::class.java) |
||||
} |
||||
|
||||
@Test |
||||
fun `getForEntity with reified type parameters, String and varargs`() { |
||||
val url = "https://spring.io" |
||||
val var1 = "var1" |
||||
val var2 = "var2" |
||||
template.getForEntity<Foo>(url, var1, var2) |
||||
verify(template, times(1)).getForEntity(url, Foo::class.java, var1, var2) |
||||
} |
||||
|
||||
@Test |
||||
fun `getForEntity with reified type parameters and Map`() { |
||||
val url = "https://spring.io" |
||||
val vars = mapOf(Pair("key1", "value1"), Pair("key2", "value2")) |
||||
template.getForEntity<Foo>(url, vars) |
||||
verify(template, times(1)).getForEntity(url, Foo::class.java, vars) |
||||
} |
||||
|
||||
@Test |
||||
fun `patchForObject with reified type parameters, String and varargs`() { |
||||
val url = "https://spring.io" |
||||
val body: Any = "body" |
||||
val var1 = "var1" |
||||
val var2 = "var2" |
||||
template.patchForObject<Foo>(url, body, var1, var2) |
||||
verify(template, times(1)).patchForObject(url, body, Foo::class.java, var1, var2) |
||||
} |
||||
|
||||
@Test |
||||
fun `patchForObject with reified type parameters, String and Map`() { |
||||
val url = "https://spring.io" |
||||
val body: Any = "body" |
||||
val vars = mapOf(Pair("key1", "value1"), Pair("key2", "value2")) |
||||
template.patchForObject<Foo>(url, body, vars) |
||||
verify(template, times(1)).patchForObject(url, body, Foo::class.java, vars) |
||||
} |
||||
|
||||
@Test |
||||
fun `patchForObject with reified type parameters`() { |
||||
val url = "https://spring.io" |
||||
val body: Any = "body" |
||||
template.patchForObject<Foo>(url, body) |
||||
verify(template, times(1)).patchForObject(url, body, Foo::class.java) |
||||
} |
||||
|
||||
@Test |
||||
fun `postForObject with reified type parameters, String and varargs`() { |
||||
val url = "https://spring.io" |
||||
val body: Any = "body" |
||||
val var1 = "var1" |
||||
val var2 = "var2" |
||||
template.postForObject<Foo>(url, body, var1, var2) |
||||
verify(template, times(1)).postForObject(url, body, Foo::class.java, var1, var2) |
||||
} |
||||
|
||||
@Test |
||||
fun `postForObject with reified type parameters, String and Map`() { |
||||
val url = "https://spring.io" |
||||
val body: Any = "body" |
||||
val vars = mapOf(Pair("key1", "value1"), Pair("key2", "value2")) |
||||
template.postForObject<Foo>(url, body, vars) |
||||
verify(template, times(1)).postForObject(url, body, Foo::class.java, vars) |
||||
} |
||||
|
||||
@Test |
||||
fun `postForObject with reified type parameters`() { |
||||
val url = "https://spring.io" |
||||
val body: Any = "body" |
||||
template.postForObject<Foo>(url, body) |
||||
verify(template, times(1)).postForObject(url, body, Foo::class.java) |
||||
} |
||||
|
||||
@Test |
||||
fun `postForEntity with reified type parameters, String and varargs`() { |
||||
val url = "https://spring.io" |
||||
val body: Any = "body" |
||||
val var1 = "var1" |
||||
val var2 = "var2" |
||||
template.postForEntity<Foo>(url, body, var1, var2) |
||||
verify(template, times(1)).postForEntity(url, body, Foo::class.java, var1, var2) |
||||
} |
||||
|
||||
@Test |
||||
fun `postForEntity with reified type parameters, String and Map`() { |
||||
val url = "https://spring.io" |
||||
val body: Any = "body" |
||||
val vars = mapOf(Pair("key1", "value1"), Pair("key2", "value2")) |
||||
template.postForEntity<Foo>(url, body, vars) |
||||
verify(template, times(1)).postForEntity(url, body, Foo::class.java, vars) |
||||
} |
||||
|
||||
@Test |
||||
fun `postForEntity with reified type parameters`() { |
||||
val url = "https://spring.io" |
||||
val body: Any = "body" |
||||
template.postForEntity<Foo>(url, body) |
||||
verify(template, times(1)).postForEntity(url, body, Foo::class.java) |
||||
} |
||||
|
||||
@Test |
||||
fun `exchange with reified type parameters, String, HttpMethod, HttpEntity and varargs`() { |
||||
val url = "https://spring.io" |
||||
val method = HttpMethod.GET |
||||
val entity = mock<HttpEntity<Foo>>() |
||||
val var1 = "var1" |
||||
val var2 = "var2" |
||||
template.exchange<List<Foo>>(url, method, entity, var1, var2) |
||||
verify(template, times(1)).exchange(url, method, entity, object : ParameterizedTypeReference<List<Foo>>() {}, var1, var2) |
||||
} |
||||
|
||||
@Test |
||||
fun `exchange with reified type parameters, String, HttpMethod, HttpEntity and Map`() { |
||||
val url = "https://spring.io" |
||||
val method = HttpMethod.GET |
||||
val entity = mock<HttpEntity<Foo>>() |
||||
val vars = mapOf(Pair("key1", "value1"), Pair("key2", "value2")) |
||||
template.exchange<List<Foo>>(url, method, entity, vars) |
||||
verify(template, times(1)).exchange(url, method, entity, object : ParameterizedTypeReference<List<Foo>>() {}, vars) |
||||
} |
||||
|
||||
@Test |
||||
fun `exchange with reified type parameters, String, HttpMethod, HttpEntity`() { |
||||
val url = "https://spring.io" |
||||
val method = HttpMethod.GET |
||||
val entity = mock<HttpEntity<Foo>>() |
||||
template.exchange<List<Foo>>(url, method, entity) |
||||
verify(template, times(1)).exchange(url, method, entity, object : ParameterizedTypeReference<List<Foo>>() {}) |
||||
} |
||||
|
||||
@Test |
||||
fun `exchange with reified type parameters, String, HttpEntity`() { |
||||
val entity = mock<RequestEntity<Foo>>() |
||||
template.exchange<List<Foo>>(entity) |
||||
verify(template, times(1)).exchange(entity, object : ParameterizedTypeReference<List<Foo>>() {}) |
||||
} |
||||
|
||||
@Test |
||||
fun `RestOperations are available`() { |
||||
val extensions = Class.forName("org.springframework.boot.test.web.client.TestRestTemplateExtensionsKt") |
||||
ReflectionUtils.doWithMethods(RestOperations::class.java) { method -> |
||||
arrayOf(ParameterizedTypeReference::class, Class::class).forEach { kClass -> |
||||
if (method.parameterTypes.contains(kClass.java)) { |
||||
val parameters = mutableListOf<Class<*>>(TestRestTemplate::class.java).apply { addAll(method.parameterTypes.filter { it != kClass.java }) } |
||||
val f = extensions.getDeclaredMethod(method.name, *parameters.toTypedArray()).kotlinFunction!! |
||||
Assert.assertEquals(1, f.typeParameters.size) |
||||
Assert.assertEquals(listOf(Any::class.createType()), f.typeParameters[0].upperBounds) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
class Foo |
||||
|
||||
} |
||||
Loading…
Reference in new issue