Skip to content

Commit dac387e

Browse files
committed
Add Kotlin support for RestTestClient
1 parent bbc8590 commit dac387e

File tree

9 files changed

+190
-27
lines changed

9 files changed

+190
-27
lines changed

json-unit-kotest/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@
143143
<plugin>
144144
<groupId>org.jetbrains.dokka</groupId>
145145
<artifactId>dokka-maven-plugin</artifactId>
146-
<version>2.0.0</version>
146+
<version>2.1.0-Beta</version>
147147
<executions>
148148
<execution>
149149
<phase>package</phase>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package net.javacrumbs.jsonunit.spring;
2+
3+
import java.nio.charset.Charset;
4+
import java.nio.charset.StandardCharsets;
5+
import org.jspecify.annotations.Nullable;
6+
import org.springframework.http.MediaType;
7+
8+
class CharsetUtils {
9+
static Charset getCharset(@Nullable MediaType contentType) {
10+
if (contentType != null && contentType.getCharset() != null) {
11+
return contentType.getCharset();
12+
} else {
13+
return StandardCharsets.UTF_8;
14+
}
15+
}
16+
}

json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/RestTestClientJsonMatcher.java

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
package net.javacrumbs.jsonunit.spring;
22

3-
import java.nio.charset.Charset;
3+
import static net.javacrumbs.jsonunit.spring.RestTestClientUtils.getContentAsString;
4+
45
import java.util.function.Consumer;
56
import java.util.function.Function;
67
import net.javacrumbs.jsonunit.core.Configuration;
78
import net.javacrumbs.jsonunit.core.internal.matchers.InternalMatcher;
8-
import org.jspecify.annotations.Nullable;
99
import org.springframework.test.web.servlet.client.EntityExchangeResult;
1010

1111
/**
@@ -51,15 +51,5 @@ private JsonUnitWebTestClientMatcher(
5151
public void accept(EntityExchangeResult<byte[]> result) {
5252
doMatch(getContentAsString(result));
5353
}
54-
55-
private static @Nullable String getContentAsString(EntityExchangeResult<byte[]> result) {
56-
Charset charset = getCharset(result);
57-
byte[] responseBody = result.getResponseBody();
58-
return responseBody != null ? new String(responseBody, charset) : null;
59-
}
60-
61-
private static Charset getCharset(EntityExchangeResult<byte[]> result) {
62-
return Utils.getCharset(result.getResponseHeaders().getContentType());
63-
}
6454
}
6555
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package net.javacrumbs.jsonunit.spring;
2+
3+
import java.nio.charset.Charset;
4+
import org.jspecify.annotations.Nullable;
5+
import org.springframework.test.web.servlet.client.EntityExchangeResult;
6+
7+
class RestTestClientUtils {
8+
static @Nullable String getContentAsString(EntityExchangeResult<byte[]> result) {
9+
Charset charset = getCharset(result);
10+
byte[] responseBody = result.getResponseBody();
11+
if (responseBody != null) {
12+
return new String(responseBody, charset);
13+
} else {
14+
return null;
15+
}
16+
}
17+
18+
private static Charset getCharset(EntityExchangeResult<byte[]> result) {
19+
return CharsetUtils.getCharset(result.getResponseHeaders().getContentType());
20+
}
21+
}

json-unit-spring/src/main/java/net/javacrumbs/jsonunit/spring/WebTestClientJsonMatcher.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package net.javacrumbs.jsonunit.spring;
22

3-
import static net.javacrumbs.jsonunit.spring.Utils.getContentAsString;
3+
import static net.javacrumbs.jsonunit.spring.WebTestClientUtils.getContentAsString;
44

55
import java.util.function.Consumer;
66
import java.util.function.Function;
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package net.javacrumbs.jsonunit.spring;
22

33
import java.nio.charset.Charset;
4-
import java.nio.charset.StandardCharsets;
54
import org.jspecify.annotations.Nullable;
6-
import org.springframework.http.MediaType;
75
import org.springframework.test.web.reactive.server.EntityExchangeResult;
86

9-
class Utils {
7+
class WebTestClientUtils {
108
static @Nullable String getContentAsString(EntityExchangeResult<byte[]> result) {
119
Charset charset = getCharset(result);
1210
byte[] responseBody = result.getResponseBody();
@@ -18,14 +16,6 @@ class Utils {
1816
}
1917

2018
private static Charset getCharset(EntityExchangeResult<byte[]> result) {
21-
return getCharset(result.getResponseHeaders().getContentType());
22-
}
23-
24-
static Charset getCharset(@Nullable MediaType contentType) {
25-
if (contentType != null && contentType.getCharset() != null) {
26-
return contentType.getCharset();
27-
} else {
28-
return StandardCharsets.UTF_8;
29-
}
19+
return CharsetUtils.getCharset(result.getResponseHeaders().getContentType());
3020
}
3121
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package net.javacrumbs.jsonunit.spring
2+
3+
import net.javacrumbs.jsonunit.assertj.JsonAssert
4+
import net.javacrumbs.jsonunit.assertj.JsonAssertions
5+
import net.javacrumbs.jsonunit.spring.RestTestClientUtils.getContentAsString
6+
import net.javacrumbs.jsonunit.spring.WebTestClientUtils.getContentAsString
7+
import org.springframework.test.web.servlet.client.RestTestClient
8+
9+
/**
10+
* Example usage:
11+
* ```
12+
* client.get().uri(path).accept(APPLICATION_JSON)
13+
* .exchange()
14+
* .jsonContent { isEqualTo(CORRECT_JSON) }
15+
* ```
16+
*/
17+
fun RestTestClient.BodyContentSpec.jsonContent(
18+
matcher: JsonAssert.ConfigurableJsonAssert.() -> Unit
19+
): RestTestClient.BodyContentSpec = consumeWith { result ->
20+
matcher(JsonAssertions.assertThatJson(getContentAsString(result)))
21+
}

json-unit-spring/src/main/kotlin/net/javacrumbs/jsonunit/spring/WebTestClientJsonMatcherDsl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package net.javacrumbs.jsonunit.spring
22

33
import net.javacrumbs.jsonunit.assertj.JsonAssert
44
import net.javacrumbs.jsonunit.assertj.JsonAssertions
5-
import net.javacrumbs.jsonunit.spring.Utils.getContentAsString
5+
import net.javacrumbs.jsonunit.spring.WebTestClientUtils.getContentAsString
66
import org.springframework.test.web.reactive.server.WebTestClient
77

88
/**
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Copyright 2009-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5+
* the License. You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10+
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11+
* specific language governing permissions and limitations under the License.
12+
*/
13+
package net.javacrumbs.jsonunit.spring.testit
14+
15+
import net.javacrumbs.jsonunit.core.listener.Difference
16+
import net.javacrumbs.jsonunit.core.listener.DifferenceContext
17+
import net.javacrumbs.jsonunit.core.listener.DifferenceListener
18+
import net.javacrumbs.jsonunit.spring.jsonContent
19+
import net.javacrumbs.jsonunit.spring.testit.demo.ExampleController
20+
import net.javacrumbs.jsonunit.spring.testit.demo.ExampleController.CORRECT_JSON
21+
import net.javacrumbs.jsonunit.spring.testit.demo.SpringConfig
22+
import org.assertj.core.api.Assertions.assertThatThrownBy
23+
import org.junit.jupiter.api.BeforeEach
24+
import org.junit.jupiter.api.Test
25+
import org.junit.jupiter.api.extension.ExtendWith
26+
import org.mockito.ArgumentMatchers.any
27+
import org.mockito.Mockito.mock
28+
import org.mockito.Mockito.verify
29+
import org.springframework.beans.factory.annotation.Autowired
30+
import org.springframework.http.MediaType.APPLICATION_JSON
31+
import org.springframework.test.context.ContextConfiguration
32+
import org.springframework.test.context.junit.jupiter.SpringExtension
33+
import org.springframework.test.context.web.WebAppConfiguration
34+
import org.springframework.test.web.servlet.client.RestTestClient
35+
import org.springframework.web.context.WebApplicationContext
36+
37+
@ExtendWith(SpringExtension::class)
38+
@ContextConfiguration(classes = [SpringConfig::class])
39+
@WebAppConfiguration
40+
internal class KotlinRestTestClientTest {
41+
@Autowired lateinit var wac: WebApplicationContext
42+
43+
lateinit var client: RestTestClient
44+
45+
@BeforeEach
46+
fun setUp() {
47+
client = RestTestClient.bindToApplicationContext(wac).build()
48+
}
49+
50+
@Test
51+
fun shouldPassIfEqualsWithProduces() {
52+
exec("/sampleProduces")
53+
.expectBody()
54+
.jsonContent { isEqualTo(CORRECT_JSON) }
55+
.jsonContent { node("result.string").isString().isEqualTo("stringValue") }
56+
}
57+
58+
@Test
59+
fun shouldPassIfEqualsWithIsoEncoding() {
60+
exec("/sampleIso").expectBody().jsonContent { node("result").isEqualTo(ExampleController.ISO_VALUE) }
61+
}
62+
63+
@Test
64+
fun shouldPassIfEquals() {
65+
exec().expectBody().jsonContent { isEqualTo(CORRECT_JSON) }
66+
}
67+
68+
@Test
69+
fun isEqualToShouldFailIfDoesNotEqual() {
70+
val listener = mock(DifferenceListener::class.java)
71+
assertThatThrownBy {
72+
exec().expectBody().jsonContent {
73+
withDifferenceListener(listener).isEqualTo(CORRECT_JSON.replace("stringValue", "stringValue2"))
74+
}
75+
}
76+
.hasMessageStartingWith(
77+
"""
78+
JSON documents are different:
79+
Different value found in node "result.string", expected: <"stringValue2"> but was: <"stringValue">.
80+
81+
"""
82+
.trimIndent()
83+
)
84+
verify(listener).diff(any(Difference::class.java), any(DifferenceContext::class.java))
85+
}
86+
87+
@Test
88+
fun isEqualToInNodeFailIfDoesNotEqual() {
89+
assertThatThrownBy {
90+
exec().expectBody().jsonContent { node("result.string").isString().isEqualTo("stringValue2") }
91+
}
92+
.hasMessage(
93+
"[Different value found in node \"result.string\"] \n" +
94+
"expected: \"stringValue2\"\n" +
95+
" but was: \"stringValue\""
96+
)
97+
}
98+
99+
@Test
100+
fun errorOnEmptyResponse() {
101+
assertThatThrownBy { exec("/empty").expectBody().jsonContent { isObject() } }
102+
.hasMessageStartingWith("Node \"\" has invalid type, expected: <object> but was: <null>.")
103+
}
104+
105+
@Test
106+
fun isNullShouldPassOnNull() {
107+
exec().expectBody().jsonContent { node("result.null").isNull() }
108+
}
109+
110+
@Test
111+
fun isNullShouldFailOnNonNull() {
112+
assertThatThrownBy { exec().expectBody().jsonContent { node("result.string").isNull() } }
113+
.hasMessageStartingWith(
114+
"Node \"result.string\" has invalid type, expected: <null> but was: <\"stringValue\">."
115+
)
116+
}
117+
118+
private fun exec(path: String = "/sample"): RestTestClient.ResponseSpec {
119+
try {
120+
return client.get().uri(path).accept(APPLICATION_JSON).exchange().expectStatus().isOk()
121+
} catch (e: Exception) {
122+
throw IllegalStateException(e)
123+
}
124+
}
125+
}

0 commit comments

Comments
 (0)