Add Kotlin extensions for RestTestClient

Closes gh-35558
This commit is contained in:
Stéphane Nicoll 2025-10-01 10:51:39 +02:00
parent 741107969a
commit 8cad5711f5
2 changed files with 130 additions and 0 deletions

View File

@ -0,0 +1,43 @@
/*
* Copyright 2002-present 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
*
* https://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.test.web.servlet.client
import org.springframework.core.ParameterizedTypeReference
import org.springframework.test.web.servlet.client.RestTestClient.BodySpec
import org.springframework.test.web.servlet.client.RestTestClient.ResponseSpec
/**
* Extension for [ResponseSpec.expectBody] providing an `expectBody<Foo>()` variant
* leveraging Kotlin reified type parameters. This extension is not subject ot type
* erasure and retains actual generic type arguments.
*
* @author Sebastien Deleuze
* @author Arjen Poutsma
* @author Stephane Nicoll
* @since 7.0
*/
inline fun <reified B : Any> ResponseSpec.expectBody(): BodySpec<B, *> =
expectBody(object : ParameterizedTypeReference<B>() {})
/**
* Extension for [ResponseSpec.returnResult] providing a `returnResult<Foo>()` variant.
*
* @author Sebastien Deleuze
* @since 7.0
*/
inline fun <reified T : Any> ResponseSpec.returnResult(): EntityExchangeResult<T> =
returnResult(object : ParameterizedTypeReference<T>() {})

View File

@ -0,0 +1,87 @@
/*
* Copyright 2002-present 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
*
* https://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.test.web.servlet.client
import io.mockk.mockk
import io.mockk.verify
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.core.ParameterizedTypeReference
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController
/**
* Mock object based tests for [RestTestClient] Kotlin extensions
*
* @author Sebastien Deleuze
* @author Stephane Nicoll
*/
class RestTestClientExtensionsTests {
private val responseSpec = mockk<RestTestClient.ResponseSpec>(relaxed = true)
@Test
fun `ResponseSpec#expectBody with reified type parameters`() {
responseSpec.expectBody<Foo>()
verify { responseSpec.expectBody(object : ParameterizedTypeReference<Foo>() {}) }
}
@Test
fun `KotlinBodySpec#isEqualTo`() {
RestTestClient
.bindToController(TestController())
.build()
.get().uri("/").exchange().expectBody<String>().isEqualTo("foo")
}
@Test
fun `KotlinBodySpec#consumeWith`() {
RestTestClient
.bindToController(TestController())
.build()
.get().uri("/").exchange().expectBody<String>()
.consumeWith { assertThat(it.responseBody).isEqualTo("foo") }
}
@Test
fun `KotlinBodySpec#returnResult`() {
RestTestClient
.bindToController(TestController())
.build()
.get().uri("/").exchange().expectBody<String>().returnResult()
.apply { assertThat(responseBody).isEqualTo("foo") }
}
@Test
fun `ResponseSpec#returnResult with reified type parameters`() {
responseSpec.returnResult<Foo>()
verify { responseSpec.returnResult(object : ParameterizedTypeReference<Foo>() {}) }
}
class Foo
@RestController
class TestController {
@GetMapping("/")
fun home() = "foo"
}
}