Make ResponseSpec.expectBody Kotlin extension usable
Prior to this commit, due to KT-5464 type inference issue there was not proper way to provide body expectations with WebTestClient. This commit provides a workaround by updating the existing Kotlin extension to return a Kotlin compatible API. Issue: SPR-15692
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
package org.springframework.test.web.reactive.server
|
||||
|
||||
import org.reactivestreams.Publisher
|
||||
import org.springframework.test.util.AssertionErrors.assertEquals
|
||||
import org.springframework.test.web.reactive.server.WebTestClient.*
|
||||
|
||||
/**
|
||||
@@ -30,14 +31,55 @@ inline fun <reified T : Any, S : Publisher<T>> RequestBodySpec.body(publisher: S
|
||||
= body(publisher, T::class.java)
|
||||
|
||||
/**
|
||||
* Extension for [ResponseSpec.expectBody] providing a `expectBody<Foo>()` variant.
|
||||
* Extension for [ResponseSpec.expectBody] providing an `expectBody<Foo>()` variant and
|
||||
* a workaround for [KT-5464](https://youtrack.jetbrains.com/issue/KT-5464) which
|
||||
* prevents to use `WebTestClient.BodySpec` in Kotlin.
|
||||
*
|
||||
* @author Sebastien Deleuze
|
||||
* @since 5.0
|
||||
*/
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
inline fun <reified B : Any> ResponseSpec.expectBody(): BodySpec<B, *> =
|
||||
expectBody(B::class.java)
|
||||
inline fun <reified B : Any> ResponseSpec.expectBody(): KotlinBodySpec<B> =
|
||||
expectBody(B::class.java).returnResult().let {
|
||||
object : KotlinBodySpec<B> {
|
||||
|
||||
override fun isEqualTo(expected: B): KotlinBodySpec<B> = it
|
||||
.assertWithDiagnostics({ assertEquals("Response body", expected, it.responseBody) })
|
||||
.let { this }
|
||||
|
||||
override fun consumeWith(consumer: (EntityExchangeResult<B>) -> Unit): KotlinBodySpec<B> =
|
||||
it
|
||||
.assertWithDiagnostics({ consumer.invoke(it) })
|
||||
.let { this }
|
||||
|
||||
override fun returnResult(): EntityExchangeResult<B> = it
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Kotlin compliant `WebTestClient.BodySpec` for expectations on the response body decoded
|
||||
* to a single Object, see [KT-5464](https://youtrack.jetbrains.com/issue/KT-5464) for
|
||||
* more details.
|
||||
* @since 5.0.6
|
||||
*/
|
||||
interface KotlinBodySpec<B> {
|
||||
|
||||
/**
|
||||
* Assert the extracted body is equal to the given value.
|
||||
*/
|
||||
fun isEqualTo(expected: B): KotlinBodySpec<B>
|
||||
|
||||
/**
|
||||
* Assert the exchange result with the given consumer.
|
||||
*/
|
||||
fun consumeWith(consumer: (EntityExchangeResult<B>) -> Unit): KotlinBodySpec<B>
|
||||
|
||||
/**
|
||||
* Exit the chained API and return an `ExchangeResult` with the
|
||||
* decoded response content.
|
||||
*/
|
||||
fun returnResult(): EntityExchangeResult<B>
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension for [ResponseSpec.expectBodyList] providing a `expectBodyList<Foo>()` variant.
|
||||
|
||||
@@ -19,12 +19,15 @@ package org.springframework.test.web.reactive.server
|
||||
import com.nhaarman.mockito_kotlin.mock
|
||||
import com.nhaarman.mockito_kotlin.times
|
||||
import com.nhaarman.mockito_kotlin.verify
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Answers
|
||||
import org.mockito.Mock
|
||||
import org.mockito.junit.MockitoJUnitRunner
|
||||
import org.reactivestreams.Publisher
|
||||
import org.springframework.web.reactive.function.server.ServerResponse.*
|
||||
import org.springframework.web.reactive.function.server.router
|
||||
|
||||
/**
|
||||
* Mock object based tests for [WebTestClient] Kotlin extensions
|
||||
@@ -54,6 +57,30 @@ class WebTestClientExtensionsTests {
|
||||
verify(responseSpec, times(1)).expectBody(Foo::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `KotlinBodySpec#isEqualTo`() {
|
||||
WebTestClient
|
||||
.bindToRouterFunction( router { GET("/") { ok().syncBody("foo") } } )
|
||||
.build()
|
||||
.get().uri("/").exchange().expectBody<String>().isEqualTo("foo")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `KotlinBodySpec#consumeWith`() {
|
||||
WebTestClient
|
||||
.bindToRouterFunction( router { GET("/") { ok().syncBody("foo") } } )
|
||||
.build()
|
||||
.get().uri("/").exchange().expectBody<String>().consumeWith { assertEquals("foo", it.responseBody) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `KotlinBodySpec#returnResult`() {
|
||||
WebTestClient
|
||||
.bindToRouterFunction( router { GET("/") { ok().syncBody("foo") } } )
|
||||
.build()
|
||||
.get().uri("/").exchange().expectBody<String>().returnResult().apply { assertEquals("foo", responseBody) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ResponseSpec#expectBodyList with reified type parameters`() {
|
||||
responseSpec.expectBodyList<Foo>()
|
||||
|
||||
@@ -663,13 +663,11 @@ class SpecificationLikeTests {
|
||||
[[kotlin-webtestclient-issue]]
|
||||
==== `WebTestClient` type inference issue in Kotlin
|
||||
|
||||
`WebTestClient` is not usable yet in Kotlin due to a
|
||||
https://youtrack.jetbrains.com/issue/KT-5464[type inference issue] which is
|
||||
expected to be fixed as of Kotlin 1.3. You can watch
|
||||
https://jira.spring.io/browse/SPR-16057[SPR-16057] for up-to-date information. Meanwhile,
|
||||
the proposed alternative is to use directly `WebClient` with its Reactor and Spring Kotlin
|
||||
extensions to perform integration tests on an embedded WebFlux server.
|
||||
Due to a https://youtrack.jetbrains.com/issue/KT-5464[type inference issue], make sure to
|
||||
use Kotlin `expectBody` extension (like `.expectBody<String>().isEqualTo("foo")`) since it
|
||||
provides a workaround for the Kotlin issue with the Java API.
|
||||
|
||||
See also the related https://jira.spring.io/browse/SPR-16057[SPR-16057] issue.
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user