Preserve generic type info in awaitEntity()

awaitEntity() used T::class.java which erases generic type
information (e.g. List<Foo> becomes just List). Use the
reified toEntity<T>() extension instead, which preserves
full generic type via ParameterizedTypeReference.

Closes gh-36834
Signed-off-by: wushiyuanmaimob <wushiyuanwork@outlook.com>
This commit is contained in:
wushiyuanmaimob
2026-06-02 12:26:41 +02:00
committed by Sébastien Deleuze
parent dd72b9eb4b
commit 85a8868bae
2 changed files with 11 additions and 3 deletions
@@ -236,7 +236,7 @@ inline fun <reified T : Any> WebClient.ResponseSpec.toEntityFlux(): Mono<Respons
suspend inline fun <reified T : Any> WebClient.ResponseSpec.awaitEntity(): ResponseEntity<T> {
val context = currentCoroutineContext().minusKey(Job.Key)
return withContext(context.toReactorContext()) {
toEntity(T::class.java).awaitSingle()
toEntity<T>().awaitSingle()
}
}
@@ -219,6 +219,14 @@ class WebClientExtensionsTests {
verify { responseSpec.toEntityFlux(object : ParameterizedTypeReference<List<Foo>>() {}) }
}
@Test
suspend fun `awaitEntity preserves generic type information`() {
val spec = mockk<WebClient.ResponseSpec>()
val entity = mockk<ResponseEntity<List<Foo>>>()
every { spec.toEntity(any<ParameterizedTypeReference<List<Foo>>>()) } returns Mono.just(entity)
assertThat(spec.awaitEntity<List<Foo>>()).isEqualTo(entity)
}
@Test
fun `ResponseSpec#awaitEntity with coroutine context propagation`() {
val exchangeFunction = mockk<ExchangeFunction>()
@@ -230,7 +238,7 @@ class WebClientExtensionsTests {
every { mockResponse.statusCode() } returns HttpStatus.OK
every { mockResponse.headers() } returns mockClientHeaders
every { mockClientHeaders.asHttpHeaders() } returns HttpHeaders()
every { mockResponse.bodyToMono(Foo::class.java) } returns Mono.just(foo)
every { mockResponse.bodyToMono(any<ParameterizedTypeReference<Foo>>()) } returns Mono.just(foo)
runBlocking(FooContextElement(foo)) {
val responseEntity = WebClient.builder()
.exchangeFunction(exchangeFunction)
@@ -258,7 +266,7 @@ class WebClientExtensionsTests {
every { mockResponse.statusCode() } returns HttpStatus.OK
every { mockResponse.headers() } returns mockClientHeaders
every { mockClientHeaders.asHttpHeaders() } returns HttpHeaders()
every { mockResponse.bodyToMono(Foo::class.java) } returns Mono.just(foo)
every { mockResponse.bodyToMono(any<ParameterizedTypeReference<Foo>>()) } returns Mono.just(foo)
runBlocking {
val responseEntity = WebClient.builder()
.exchangeFunction(exchangeFunction)