Browse Source

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
pull/1793/head
sdeleuze 8 years ago
parent
commit
568a0b5b79
  1. 48
      spring-test/src/main/kotlin/org/springframework/test/web/reactive/server/WebTestClientExtensions.kt
  2. 27
      spring-test/src/test/kotlin/org/springframework/test/web/reactive/server/WebTestClientExtensionsTests.kt
  3. 10
      src/docs/asciidoc/languages/kotlin.adoc

48
spring-test/src/main/kotlin/org/springframework/test/web/reactive/server/WebTestClientExtensions.kt

@ -17,6 +17,7 @@ @@ -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 @@ -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.

27
spring-test/src/test/kotlin/org/springframework/test/web/reactive/server/WebTestClientExtensionsTests.kt

@ -19,12 +19,15 @@ package org.springframework.test.web.reactive.server @@ -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 { @@ -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>()

10
src/docs/asciidoc/languages/kotlin.adoc

@ -663,13 +663,11 @@ class SpecificationLikeTests { @@ -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.

Loading…
Cancel
Save