Skip to content

Commit 568a0b5

Browse files
committed
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
1 parent 51be8a7 commit 568a0b5

File tree

3 files changed

+76
-9
lines changed

3 files changed

+76
-9
lines changed

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

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.test.web.reactive.server
1818

1919
import org.reactivestreams.Publisher
20+
import org.springframework.test.util.AssertionErrors.assertEquals
2021
import org.springframework.test.web.reactive.server.WebTestClient.*
2122

2223
/**
@@ -30,14 +31,55 @@ inline fun <reified T : Any, S : Publisher<T>> RequestBodySpec.body(publisher: S
3031
= body(publisher, T::class.java)
3132

3233
/**
33-
* Extension for [ResponseSpec.expectBody] providing a `expectBody<Foo>()` variant.
34+
* Extension for [ResponseSpec.expectBody] providing an `expectBody<Foo>()` variant and
35+
* a workaround for [KT-5464](https://youtrack.jetbrains.com/issue/KT-5464) which
36+
* prevents to use `WebTestClient.BodySpec` in Kotlin.
3437
*
3538
* @author Sebastien Deleuze
3639
* @since 5.0
3740
*/
3841
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
39-
inline fun <reified B : Any> ResponseSpec.expectBody(): BodySpec<B, *> =
40-
expectBody(B::class.java)
42+
inline fun <reified B : Any> ResponseSpec.expectBody(): KotlinBodySpec<B> =
43+
expectBody(B::class.java).returnResult().let {
44+
object : KotlinBodySpec<B> {
45+
46+
override fun isEqualTo(expected: B): KotlinBodySpec<B> = it
47+
.assertWithDiagnostics({ assertEquals("Response body", expected, it.responseBody) })
48+
.let { this }
49+
50+
override fun consumeWith(consumer: (EntityExchangeResult<B>) -> Unit): KotlinBodySpec<B> =
51+
it
52+
.assertWithDiagnostics({ consumer.invoke(it) })
53+
.let { this }
54+
55+
override fun returnResult(): EntityExchangeResult<B> = it
56+
}
57+
}
58+
59+
/**
60+
* Kotlin compliant `WebTestClient.BodySpec` for expectations on the response body decoded
61+
* to a single Object, see [KT-5464](https://youtrack.jetbrains.com/issue/KT-5464) for
62+
* more details.
63+
* @since 5.0.6
64+
*/
65+
interface KotlinBodySpec<B> {
66+
67+
/**
68+
* Assert the extracted body is equal to the given value.
69+
*/
70+
fun isEqualTo(expected: B): KotlinBodySpec<B>
71+
72+
/**
73+
* Assert the exchange result with the given consumer.
74+
*/
75+
fun consumeWith(consumer: (EntityExchangeResult<B>) -> Unit): KotlinBodySpec<B>
76+
77+
/**
78+
* Exit the chained API and return an `ExchangeResult` with the
79+
* decoded response content.
80+
*/
81+
fun returnResult(): EntityExchangeResult<B>
82+
}
4183

4284
/**
4385
* Extension for [ResponseSpec.expectBodyList] providing a `expectBodyList<Foo>()` variant.

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@ package org.springframework.test.web.reactive.server
1919
import com.nhaarman.mockito_kotlin.mock
2020
import com.nhaarman.mockito_kotlin.times
2121
import com.nhaarman.mockito_kotlin.verify
22+
import org.junit.Assert.assertEquals
2223
import org.junit.Test
2324
import org.junit.runner.RunWith
2425
import org.mockito.Answers
2526
import org.mockito.Mock
2627
import org.mockito.junit.MockitoJUnitRunner
2728
import org.reactivestreams.Publisher
29+
import org.springframework.web.reactive.function.server.ServerResponse.*
30+
import org.springframework.web.reactive.function.server.router
2831

2932
/**
3033
* Mock object based tests for [WebTestClient] Kotlin extensions
@@ -54,6 +57,30 @@ class WebTestClientExtensionsTests {
5457
verify(responseSpec, times(1)).expectBody(Foo::class.java)
5558
}
5659

60+
@Test
61+
fun `KotlinBodySpec#isEqualTo`() {
62+
WebTestClient
63+
.bindToRouterFunction( router { GET("/") { ok().syncBody("foo") } } )
64+
.build()
65+
.get().uri("/").exchange().expectBody<String>().isEqualTo("foo")
66+
}
67+
68+
@Test
69+
fun `KotlinBodySpec#consumeWith`() {
70+
WebTestClient
71+
.bindToRouterFunction( router { GET("/") { ok().syncBody("foo") } } )
72+
.build()
73+
.get().uri("/").exchange().expectBody<String>().consumeWith { assertEquals("foo", it.responseBody) }
74+
}
75+
76+
@Test
77+
fun `KotlinBodySpec#returnResult`() {
78+
WebTestClient
79+
.bindToRouterFunction( router { GET("/") { ok().syncBody("foo") } } )
80+
.build()
81+
.get().uri("/").exchange().expectBody<String>().returnResult().apply { assertEquals("foo", responseBody) }
82+
}
83+
5784
@Test
5885
fun `ResponseSpec#expectBodyList with reified type parameters`() {
5986
responseSpec.expectBodyList<Foo>()

src/docs/asciidoc/languages/kotlin.adoc

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -663,13 +663,11 @@ class SpecificationLikeTests {
663663
[[kotlin-webtestclient-issue]]
664664
==== `WebTestClient` type inference issue in Kotlin
665665

666-
`WebTestClient` is not usable yet in Kotlin due to a
667-
https://youtrack.jetbrains.com/issue/KT-5464[type inference issue] which is
668-
expected to be fixed as of Kotlin 1.3. You can watch
669-
https://jira.spring.io/browse/SPR-16057[SPR-16057] for up-to-date information. Meanwhile,
670-
the proposed alternative is to use directly `WebClient` with its Reactor and Spring Kotlin
671-
extensions to perform integration tests on an embedded WebFlux server.
666+
Due to a https://youtrack.jetbrains.com/issue/KT-5464[type inference issue], make sure to
667+
use Kotlin `expectBody` extension (like `.expectBody<String>().isEqualTo("foo")`) since it
668+
provides a workaround for the Kotlin issue with the Java API.
672669

670+
See also the related https://jira.spring.io/browse/SPR-16057[SPR-16057] issue.
673671

674672

675673

0 commit comments

Comments
 (0)