mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-24 15:49:26 +00:00
Add RestTestClient
See gh-34428 Signed-off-by: Rob Worsnop <rworsnop@gmail.com>
This commit is contained in:
+1
@@ -55,6 +55,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@WebAppConfiguration
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MockMvcClientHttpRequestFactoryTests {
|
||||
|
||||
@Autowired
|
||||
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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 java.time.Duration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.mockito.BDDMockito.mock;
|
||||
import static org.mockito.BDDMockito.when;
|
||||
|
||||
/**
|
||||
* Tests for {@link CookieAssertions}
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
public class CookieAssertionsTests {
|
||||
|
||||
private final ResponseCookie cookie = ResponseCookie.from("foo", "bar")
|
||||
.maxAge(Duration.ofMinutes(30))
|
||||
.domain("foo.com")
|
||||
.path("/foo")
|
||||
.secure(true)
|
||||
.httpOnly(true)
|
||||
.partitioned(true)
|
||||
.sameSite("Lax")
|
||||
.build();
|
||||
|
||||
private final CookieAssertions assertions = cookieAssertions(cookie);
|
||||
|
||||
|
||||
@Test
|
||||
void valueEquals() {
|
||||
assertions.valueEquals("foo", "bar");
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.valueEquals("what?!", "bar"));
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.valueEquals("foo", "what?!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void value() {
|
||||
assertions.value("foo", equalTo("bar"));
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.value("foo", equalTo("what?!")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void valueConsumer() {
|
||||
assertions.value("foo", input -> assertThat(input).isEqualTo("bar"));
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.value("foo", input -> assertThat(input).isEqualTo("what?!")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void exists() {
|
||||
assertions.exists("foo");
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.exists("what?!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotExist() {
|
||||
assertions.doesNotExist("what?!");
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.doesNotExist("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void maxAge() {
|
||||
assertions.maxAge("foo", Duration.ofMinutes(30));
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertions.maxAge("foo", Duration.ofMinutes(29)));
|
||||
|
||||
assertions.maxAge("foo", equalTo(Duration.ofMinutes(30).getSeconds()));
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertions.maxAge("foo", equalTo(Duration.ofMinutes(29).getSeconds())));
|
||||
}
|
||||
|
||||
@Test
|
||||
void domain() {
|
||||
assertions.domain("foo", "foo.com");
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.domain("foo", "what.com"));
|
||||
|
||||
assertions.domain("foo", equalTo("foo.com"));
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.domain("foo", equalTo("what.com")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void path() {
|
||||
assertions.path("foo", "/foo");
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.path("foo", "/what"));
|
||||
|
||||
assertions.path("foo", equalTo("/foo"));
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.path("foo", equalTo("/what")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void secure() {
|
||||
assertions.secure("foo", true);
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.secure("foo", false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void httpOnly() {
|
||||
assertions.httpOnly("foo", true);
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.httpOnly("foo", false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void partitioned() {
|
||||
assertions.partitioned("foo", true);
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.partitioned("foo", false));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sameSite() {
|
||||
assertions.sameSite("foo", "Lax");
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> assertions.sameSite("foo", "Strict"));
|
||||
}
|
||||
|
||||
|
||||
private CookieAssertions cookieAssertions(ResponseCookie cookie) {
|
||||
RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse response = mock();
|
||||
var headers = new HttpHeaders();
|
||||
headers.set(HttpHeaders.SET_COOKIE, cookie.toString());
|
||||
when(response.getHeaders()).thenReturn(headers);
|
||||
ExchangeResult result = new ExchangeResult(response);
|
||||
return new CookieAssertions(result, mock());
|
||||
}
|
||||
|
||||
}
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* 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 java.net.URI;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.http.ContentDisposition;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.hasItems;
|
||||
import static org.mockito.BDDMockito.mock;
|
||||
import static org.mockito.BDDMockito.when;
|
||||
|
||||
/**
|
||||
* Tests for {@link HeaderAssertions}.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class HeaderAssertionTests {
|
||||
|
||||
@Test
|
||||
void valueEquals() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("foo", "bar");
|
||||
headers.add("age", "22");
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
// Success
|
||||
assertions.valueEquals("foo", "bar");
|
||||
assertions.value("foo", s -> assertThat(s).isEqualTo("bar"));
|
||||
assertions.values("foo", strings -> assertThat(strings).containsExactly("bar"));
|
||||
assertions.valueEquals("age", 22);
|
||||
|
||||
// Missing header
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.valueEquals("what?!", "bar"));
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.valueEquals("foo", "what?!"));
|
||||
|
||||
// Wrong # of values
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.valueEquals("foo", "bar", "what?!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void valueEqualsWithMultipleValues() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("foo", "bar");
|
||||
headers.add("foo", "baz");
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
// Success
|
||||
assertions.valueEquals("foo", "bar", "baz");
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.valueEquals("foo", "bar", "what?!"));
|
||||
|
||||
// Too few values
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.valueEquals("foo", "bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void valueMatches() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
// Success
|
||||
assertions.valueMatches("Content-Type", ".*UTF-8.*");
|
||||
|
||||
// Wrong pattern
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertions.valueMatches("Content-Type", ".*ISO-8859-1.*"))
|
||||
.satisfies(ex -> assertThat(ex).hasMessage("Response header " +
|
||||
"'Content-Type'=[application/json;charset=UTF-8] does not match " +
|
||||
"[.*ISO-8859-1.*]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void valueMatchesWithNonexistentHeader() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertions.valueMatches("Content-XYZ", ".*ISO-8859-1.*"))
|
||||
.withMessage("Response header 'Content-XYZ' not found");
|
||||
}
|
||||
|
||||
@Test
|
||||
void valuesMatch() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("foo", "value1");
|
||||
headers.add("foo", "value2");
|
||||
headers.add("foo", "value3");
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
assertions.valuesMatch("foo", "val.*1", "val.*2", "val.*3");
|
||||
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertions.valuesMatch("foo", ".*", "val.*5"))
|
||||
.satisfies(ex -> assertThat(ex).hasMessage(
|
||||
"Response header 'foo' has fewer or more values [value1, value2, value3] " +
|
||||
"than number of patterns to match with [.*, val.*5]"));
|
||||
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertions.valuesMatch("foo", ".*", "val.*5", ".*"))
|
||||
.satisfies(ex -> assertThat(ex).hasMessage(
|
||||
"Response header 'foo'[1]='value2' does not match 'val.*5'"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void valueMatcher() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("foo", "bar");
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
assertions.value("foo", containsString("a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void valuesMatcher() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("foo", "bar");
|
||||
headers.add("foo", "baz");
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
assertions.values("foo", hasItems("bar", "baz"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void exists() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
// Success
|
||||
assertions.exists("Content-Type");
|
||||
|
||||
// Header should not exist
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.exists("Framework"))
|
||||
.satisfies(ex -> assertThat(ex).hasMessage("Response header 'Framework' does not exist"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotExist() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
// Success
|
||||
assertions.doesNotExist("Framework");
|
||||
|
||||
// Existing header
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.doesNotExist("Content-Type"))
|
||||
.satisfies(ex -> assertThat(ex).hasMessage("Response header " +
|
||||
"'Content-Type' exists with value=[application/json;charset=UTF-8]"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void contentTypeCompatibleWith() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_XML);
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
// Success
|
||||
assertions.contentTypeCompatibleWith(MediaType.parseMediaType("application/*"));
|
||||
assertions.contentTypeCompatibleWith("application/*");
|
||||
|
||||
// MediaTypes not compatible
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() -> assertions.contentTypeCompatibleWith(MediaType.TEXT_XML))
|
||||
.withMessage("Response header 'Content-Type'=[application/xml] is not compatible with [text/xml]");
|
||||
}
|
||||
|
||||
@Test
|
||||
void location() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setLocation(URI.create("http://localhost:8080/"));
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
// Success
|
||||
assertions.location("http://localhost:8080/");
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.location("http://localhost:8081/"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void cacheControl() {
|
||||
CacheControl control = CacheControl.maxAge(1, TimeUnit.HOURS).noTransform();
|
||||
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setCacheControl(control.getHeaderValue());
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
|
||||
// Success
|
||||
assertions.cacheControl(control);
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.cacheControl(CacheControl.noStore()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void contentDisposition() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentDispositionFormData("foo", "bar");
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
assertions.contentDisposition(ContentDisposition.formData().name("foo").filename("bar").build());
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.contentDisposition(ContentDisposition.attachment().build()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void contentLength() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentLength(100);
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
assertions.contentLength(100);
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.contentLength(200));
|
||||
}
|
||||
|
||||
@Test
|
||||
void contentType() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_JSON);
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
assertions.contentType(MediaType.APPLICATION_JSON);
|
||||
assertions.contentType("application/json");
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.contentType(MediaType.APPLICATION_XML));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void expires() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
ZonedDateTime expires = ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
|
||||
headers.setExpires(expires);
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
assertions.expires(expires.toInstant().toEpochMilli());
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.expires(expires.toInstant().toEpochMilli() + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void lastModified() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
ZonedDateTime lastModified = ZonedDateTime.of(2018, 1, 1, 0, 0, 0, 0, ZoneId.of("UTC"));
|
||||
headers.setLastModified(lastModified.toInstant().toEpochMilli());
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
assertions.lastModified(lastModified.toInstant().toEpochMilli());
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.lastModified(lastModified.toInstant().toEpochMilli() + 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void equalsDate() {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setDate("foo", 1000);
|
||||
HeaderAssertions assertions = headerAssertions(headers);
|
||||
assertions.valueEqualsDate("foo", 1000);
|
||||
|
||||
// Wrong value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.valueEqualsDate("foo", 2000));
|
||||
}
|
||||
|
||||
private HeaderAssertions headerAssertions(HttpHeaders responseHeaders) {
|
||||
RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse response = mock();
|
||||
when(response.getHeaders()).thenReturn(responseHeaders);
|
||||
ExchangeResult result = new ExchangeResult(response);
|
||||
return new HeaderAssertions(result, mock());
|
||||
}
|
||||
|
||||
}
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.Person;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.in;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Tests JSON Path assertions with {@link RestTestClient}.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class JsonPathAssertionTests {
|
||||
|
||||
private final RestTestClient client =
|
||||
RestTestClient.standaloneSetup(new MusicController())
|
||||
.configureServer(builder ->
|
||||
builder.alwaysExpect(status().isOk())
|
||||
.alwaysExpect(content().contentType(MediaType.APPLICATION_JSON))
|
||||
)
|
||||
.defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
|
||||
.build();
|
||||
|
||||
|
||||
@Test
|
||||
void exists() {
|
||||
String composerByName = "$.composers[?(@.name == '%s')]";
|
||||
String performerByName = "$.performers[?(@.name == '%s')]";
|
||||
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath(composerByName.formatted("Johann Sebastian Bach")).exists()
|
||||
.jsonPath(composerByName.formatted("Johannes Brahms")).exists()
|
||||
.jsonPath(composerByName.formatted("Edvard Grieg")).exists()
|
||||
.jsonPath(composerByName.formatted("Robert Schumann")).exists()
|
||||
.jsonPath(performerByName.formatted("Vladimir Ashkenazy")).exists()
|
||||
.jsonPath(performerByName.formatted("Yehudi Menuhin")).exists()
|
||||
.jsonPath("$.composers[0]").exists()
|
||||
.jsonPath("$.composers[1]").exists()
|
||||
.jsonPath("$.composers[2]").exists()
|
||||
.jsonPath("$.composers[3]").exists();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotExist() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.composers[?(@.name == 'Edvard Grieeeeeeg')]").doesNotExist()
|
||||
.jsonPath("$.composers[?(@.name == 'Robert Schuuuuuuman')]").doesNotExist()
|
||||
.jsonPath("$.composers[4]").doesNotExist();
|
||||
}
|
||||
|
||||
@Test
|
||||
void equality() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.composers[0].name").isEqualTo("Johann Sebastian Bach")
|
||||
.jsonPath("$.performers[1].name").isEqualTo("Yehudi Menuhin");
|
||||
|
||||
// Hamcrest matchers...
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON)
|
||||
.expectBody()
|
||||
.jsonPath("$.composers[0].name").value(equalTo("Johann Sebastian Bach"))
|
||||
.jsonPath("$.performers[1].name").value(equalTo("Yehudi Menuhin"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hamcrestMatcher() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.composers[0].name").value(startsWith("Johann"))
|
||||
.jsonPath("$.performers[0].name").value(endsWith("Ashkenazy"))
|
||||
.jsonPath("$.performers[1].name").value(containsString("di Me"))
|
||||
.jsonPath("$.composers[1].name").value(is(in(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hamcrestMatcherWithParameterizedJsonPath() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.composers[0].name").value(String.class, startsWith("Johann"))
|
||||
.jsonPath("$.composers[0].name").value(String.class, s -> assertThat(s).startsWith("Johann"))
|
||||
.jsonPath("$.composers[0].name").value(o -> assertThat((String) o).startsWith("Johann"))
|
||||
.jsonPath("$.performers[1].name").value(containsString("di Me"))
|
||||
.jsonPath("$.composers[1].name").value(is(in(Arrays.asList("Johann Sebastian Bach", "Johannes Brahms"))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEmpty() {
|
||||
client.get().uri("/music/instruments")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.clarinets").isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isNotEmpty() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.composers").isNotEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasJsonPath() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.composers").hasJsonPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotHaveJsonPath() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.audience").doesNotHaveJsonPath();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isBoolean() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.composers[0].someBoolean").isBoolean();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isNumber() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.composers[0].someDouble").isNumber();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isMap() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$").isMap();
|
||||
}
|
||||
|
||||
@Test
|
||||
void isArray() {
|
||||
client.get().uri("/music/people")
|
||||
.exchange()
|
||||
.expectBody()
|
||||
.jsonPath("$.composers").isArray();
|
||||
}
|
||||
|
||||
@RestController
|
||||
private static class MusicController {
|
||||
@GetMapping("/music/instruments")
|
||||
public Map<String, Object> getInstruments() {
|
||||
return Map.of("clarinets", List.of());
|
||||
}
|
||||
|
||||
@GetMapping("/music/people")
|
||||
public MultiValueMap<String, Person> get() {
|
||||
MultiValueMap<String, Person> map = new LinkedMultiValueMap<>();
|
||||
|
||||
map.add("composers", new Person("Johann Sebastian Bach"));
|
||||
map.add("composers", new Person("Johannes Brahms"));
|
||||
map.add("composers", new Person("Edvard Grieg"));
|
||||
map.add("composers", new Person("Robert Schumann"));
|
||||
|
||||
map.add("performers", new Person("Vladimir Ashkenazy"));
|
||||
map.add("performers", new Person("Yehudi Menuhin"));
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.web.client.MockMvcClientHttpRequestFactory;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.bind.annotation.CookieValue;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Tests that use a {@link RestTestClient} configured with a
|
||||
* {@link MockMvcClientHttpRequestFactory} that is in turn configured with a
|
||||
* {@link MockMvc} instance that uses a standalone controller
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
public class MockMvcClientHttpRequestFactoryTests {
|
||||
|
||||
private RestTestClient client;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new TestController()).build();
|
||||
this.client = RestTestClient.bindTo(mockMvc).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withResult() {
|
||||
client.get()
|
||||
.uri("/foo")
|
||||
.cookie("session", "12345")
|
||||
.exchange()
|
||||
.expectCookie().valueEquals("session", "12345")
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withError() {
|
||||
client.get()
|
||||
.uri("/error")
|
||||
.exchange()
|
||||
.expectStatus().isBadRequest()
|
||||
.expectBody().isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void withErrorAndBody() {
|
||||
client.get().uri("/errorbody")
|
||||
.exchange()
|
||||
.expectStatus().isBadRequest()
|
||||
.expectBody(String.class)
|
||||
.isEqualTo("some really bad request");
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping(value = "/foo")
|
||||
public void foo(@CookieValue("session") String session, HttpServletResponse response) throws IOException {
|
||||
response.getWriter().write("bar");
|
||||
response.addCookie(new Cookie("session", session));
|
||||
}
|
||||
|
||||
@GetMapping(value = "/error")
|
||||
public void handleError(HttpServletResponse response) throws Exception {
|
||||
response.sendError(400);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/errorbody")
|
||||
public void handleErrorWithBody(HttpServletResponse response) throws Exception {
|
||||
response.sendError(400);
|
||||
response.getWriter().write("some really bad request");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+266
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
* 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 java.io.IOException;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
import static org.mockito.BDDMockito.mock;
|
||||
import static org.mockito.BDDMockito.when;
|
||||
|
||||
/**
|
||||
* Tests for {@link StatusAssertions}.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class StatusAssertionTests {
|
||||
|
||||
@Test
|
||||
void isEqualTo() {
|
||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
||||
|
||||
// Success
|
||||
assertions.isEqualTo(HttpStatus.CONFLICT);
|
||||
assertions.isEqualTo(409);
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.isEqualTo(HttpStatus.REQUEST_TIMEOUT));
|
||||
|
||||
// Wrong status value
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.isEqualTo(408));
|
||||
}
|
||||
|
||||
@Test
|
||||
void isEqualToWithCustomStatus() {
|
||||
StatusAssertions assertions = statusAssertions(600);
|
||||
|
||||
// Success
|
||||
assertions.isEqualTo(600);
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
statusAssertions(601).isEqualTo(600));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void reasonEquals() {
|
||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
||||
|
||||
// Success
|
||||
assertions.reasonEquals("Conflict");
|
||||
|
||||
// Wrong reason
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).reasonEquals("Conflict"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusSeries1xx() {
|
||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONTINUE);
|
||||
|
||||
// Success
|
||||
assertions.is1xxInformational();
|
||||
|
||||
// Wrong series
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
statusAssertions(HttpStatus.OK).is1xxInformational());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusSeries2xx() {
|
||||
StatusAssertions assertions = statusAssertions(HttpStatus.OK);
|
||||
|
||||
// Success
|
||||
assertions.is2xxSuccessful();
|
||||
|
||||
// Wrong series
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).is2xxSuccessful());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusSeries3xx() {
|
||||
StatusAssertions assertions = statusAssertions(HttpStatus.PERMANENT_REDIRECT);
|
||||
|
||||
// Success
|
||||
assertions.is3xxRedirection();
|
||||
|
||||
// Wrong series
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).is3xxRedirection());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusSeries4xx() {
|
||||
StatusAssertions assertions = statusAssertions(HttpStatus.BAD_REQUEST);
|
||||
|
||||
// Success
|
||||
assertions.is4xxClientError();
|
||||
|
||||
// Wrong series
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).is4xxClientError());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusSeries5xx() {
|
||||
StatusAssertions assertions = statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
|
||||
// Success
|
||||
assertions.is5xxServerError();
|
||||
|
||||
// Wrong series
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
statusAssertions(HttpStatus.OK).is5xxServerError());
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesStatusValue() {
|
||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
||||
|
||||
// Success
|
||||
assertions.value(equalTo(409));
|
||||
assertions.value(greaterThan(400));
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() ->
|
||||
assertions.value(equalTo(200)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void matchesCustomStatusValue() {
|
||||
statusAssertions(600).value(equalTo(600));
|
||||
}
|
||||
|
||||
@Test
|
||||
void consumesStatusValue() {
|
||||
StatusAssertions assertions = statusAssertions(HttpStatus.CONFLICT);
|
||||
|
||||
// Success
|
||||
assertions.value((Integer value) -> assertThat(value).isEqualTo(409));
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusIsAccepted() {
|
||||
// Success
|
||||
statusAssertions(HttpStatus.ACCEPTED).isAccepted();
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isAccepted());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusIsNoContent() {
|
||||
// Success
|
||||
statusAssertions(HttpStatus.NO_CONTENT).isNoContent();
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusIsFound() {
|
||||
// Success
|
||||
statusAssertions(HttpStatus.FOUND).isFound();
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusIsSeeOther() {
|
||||
// Success
|
||||
statusAssertions(HttpStatus.SEE_OTHER).isSeeOther();
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isSeeOther());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusIsNotModified() {
|
||||
// Success
|
||||
statusAssertions(HttpStatus.NOT_MODIFIED).isNotModified();
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isNotModified());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusIsTemporaryRedirect() {
|
||||
// Success
|
||||
statusAssertions(HttpStatus.TEMPORARY_REDIRECT).isTemporaryRedirect();
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isTemporaryRedirect());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusIsPermanentRedirect() {
|
||||
// Success
|
||||
statusAssertions(HttpStatus.PERMANENT_REDIRECT).isPermanentRedirect();
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isPermanentRedirect());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusIsUnauthorized() {
|
||||
// Success
|
||||
statusAssertions(HttpStatus.UNAUTHORIZED).isUnauthorized();
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
void statusIsForbidden() {
|
||||
// Success
|
||||
statusAssertions(HttpStatus.FORBIDDEN).isForbidden();
|
||||
|
||||
// Wrong status
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> statusAssertions(HttpStatus.INTERNAL_SERVER_ERROR).isForbidden());
|
||||
}
|
||||
|
||||
private StatusAssertions statusAssertions(HttpStatus status) {
|
||||
return statusAssertions(status.value());
|
||||
}
|
||||
|
||||
private StatusAssertions statusAssertions(int status) {
|
||||
try {
|
||||
RestClient.RequestHeadersSpec.ConvertibleClientHttpResponse response = mock();
|
||||
when(response.getStatusCode()).thenReturn(HttpStatusCode.valueOf(status));
|
||||
ExchangeResult result = new ExchangeResult(response);
|
||||
return new StatusAssertions(result, mock());
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new AssertionError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.samples;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Tests with error status codes or error conditions.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class ErrorTests {
|
||||
|
||||
private final RestTestClient client = RestTestClient.standaloneSetup(new TestController()).build();
|
||||
|
||||
|
||||
@Test
|
||||
void notFound(){
|
||||
this.client.get().uri("/invalid")
|
||||
.exchange()
|
||||
.expectStatus().isNotFound();
|
||||
}
|
||||
|
||||
@Test
|
||||
void serverException() {
|
||||
this.client.get().uri("/server-error")
|
||||
.exchange()
|
||||
.expectStatus().isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping("/server-error")
|
||||
void handleAndThrowException() {
|
||||
throw new IllegalStateException("server error");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.samples;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.bind.annotation.CookieValue;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Tests with headers and cookies.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class HeaderAndCookieTests {
|
||||
|
||||
private final RestTestClient client = RestTestClient.standaloneSetup(new TestController()).build();
|
||||
|
||||
@Test
|
||||
void requestResponseHeaderPair() {
|
||||
this.client.get().uri("/header-echo")
|
||||
.header("h1", "in")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().valueEquals("h1", "in-out");
|
||||
}
|
||||
|
||||
@Test
|
||||
void headerMultipleValues() {
|
||||
this.client.get().uri("/header-multi-value")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().valueEquals("h1", "v1", "v2", "v3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void setCookies() {
|
||||
this.client.get().uri("/cookie-echo")
|
||||
.cookies(cookies -> cookies.add("k1", "v1"))
|
||||
.exchange()
|
||||
.expectHeader().valueMatches("Set-Cookie", "k1=v1");
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping("header-echo")
|
||||
ResponseEntity<Void> handleHeader(@RequestHeader("h1") String myHeader) {
|
||||
String value = myHeader + "-out";
|
||||
return ResponseEntity.ok().header("h1", value).build();
|
||||
}
|
||||
|
||||
@GetMapping("header-multi-value")
|
||||
ResponseEntity<Void> multiValue() {
|
||||
return ResponseEntity.ok().header("h1", "v1", "v2", "v3").build();
|
||||
}
|
||||
|
||||
@GetMapping("cookie-echo")
|
||||
ResponseEntity<Void> handleCookie(@CookieValue("k1") String cookieValue) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Set-Cookie", "k1=" + cookieValue);
|
||||
return new ResponseEntity<>(headers, HttpStatus.OK);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* 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.samples;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.json.JsonCompareMode;
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
/**
|
||||
* Samples of tests using {@link RestTestClient} with serialized JSON content.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class JsonContentTests {
|
||||
|
||||
private final RestTestClient client = RestTestClient.standaloneSetup(new PersonController()).build();
|
||||
|
||||
|
||||
@Test
|
||||
void jsonContentWithDefaultLenientMode() {
|
||||
this.client.get().uri("/persons")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().json("""
|
||||
[
|
||||
{"firstName":"Jane"},
|
||||
{"firstName":"Jason"},
|
||||
{"firstName":"John"}
|
||||
]
|
||||
""");
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsonContentWithStrictMode() {
|
||||
this.client.get().uri("/persons")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().json("""
|
||||
[
|
||||
{"firstName":"Jane", "lastName":"Williams"},
|
||||
{"firstName":"Jason","lastName":"Johnson"},
|
||||
{"firstName":"John", "lastName":"Smith"}
|
||||
]
|
||||
""",
|
||||
JsonCompareMode.STRICT);
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsonContentWithStrictModeAndMissingAttributes() {
|
||||
assertThatExceptionOfType(AssertionError.class).isThrownBy(() -> this.client.get().uri("/persons")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.exchange()
|
||||
.expectBody().json("""
|
||||
[
|
||||
{"firstName":"Jane"},
|
||||
{"firstName":"Jason"},
|
||||
{"firstName":"John"}
|
||||
]
|
||||
""",
|
||||
JsonCompareMode.STRICT)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsonPathIsEqualTo() {
|
||||
this.client.get().uri("/persons")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.jsonPath("$[0].firstName").isEqualTo("Jane")
|
||||
.jsonPath("$[1].firstName").isEqualTo("Jason")
|
||||
.jsonPath("$[2].firstName").isEqualTo("John");
|
||||
}
|
||||
|
||||
@Test
|
||||
void jsonPathMatches() {
|
||||
this.client.get().uri("/persons/John/Smith")
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.jsonPath("$.firstName").value(containsString("oh"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void postJsonContent() {
|
||||
this.client.post().uri("/persons")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body("""
|
||||
{"firstName":"John", "lastName":"Smith"}
|
||||
""")
|
||||
.exchange()
|
||||
.expectStatus().isCreated()
|
||||
.expectBody().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/persons")
|
||||
static class PersonController {
|
||||
|
||||
@GetMapping
|
||||
List<Person> getPersons() {
|
||||
return List.of(new Person("Jane", "Williams"), new Person("Jason", "Johnson"), new Person("John", "Smith"));
|
||||
}
|
||||
|
||||
@GetMapping("/{firstName}/{lastName}")
|
||||
Person getPerson(@PathVariable String firstName, @PathVariable String lastName) {
|
||||
return new Person(firstName, lastName);
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
ResponseEntity<String> savePerson(@RequestBody Person person) {
|
||||
return ResponseEntity.created(URI.create(String.format("/persons/%s/%s", person.getFirstName(), person.getLastName()))).build();
|
||||
}
|
||||
}
|
||||
|
||||
static class Person {
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
|
||||
public Person() {
|
||||
}
|
||||
|
||||
public Person(String firstName, String lastName) {
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return this.firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return this.lastName;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.samples;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@XmlRootElement
|
||||
class Person {
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
// No-arg constructor for XML
|
||||
public Person() {
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public Person(@JsonProperty("name") String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
}
|
||||
if (other == null || getClass() != other.getClass()) {
|
||||
return false;
|
||||
}
|
||||
Person person = (Person) other;
|
||||
return getName().equals(person.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Person[name='" + name + "']";
|
||||
}
|
||||
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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.samples;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
/**
|
||||
* Annotated controllers accepting and returning typed Objects.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class ResponseEntityTests {
|
||||
private final RestTestClient client = RestTestClient.standaloneSetup(new PersonController())
|
||||
.baseUrl("/persons")
|
||||
.build();
|
||||
|
||||
@Test
|
||||
void entity() {
|
||||
this.client.get().uri("/John")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON)
|
||||
.expectBody(Person.class).isEqualTo(new Person("John"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void entityMatcher() {
|
||||
this.client.get().uri("/John")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON)
|
||||
.expectBody(Person.class).value(Person::getName, startsWith("Joh"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void entityWithConsumer() {
|
||||
this.client.get().uri("/John")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON)
|
||||
.expectBody(Person.class)
|
||||
.consumeWith(result -> assertThat(result.getResponseBody()).isEqualTo(new Person("John")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void entityList() {
|
||||
List<Person> expected = List.of(
|
||||
new Person("Jane"), new Person("Jason"), new Person("John"));
|
||||
|
||||
this.client.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON)
|
||||
.expectBody(new ParameterizedTypeReference<List<Person>>() {}).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void entityListWithConsumer() {
|
||||
this.client.get()
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().contentType(MediaType.APPLICATION_JSON)
|
||||
.expectBody(new ParameterizedTypeReference<List<Person>>() {})
|
||||
.value(people ->
|
||||
assertThat(people).contains(new Person("Jason"))
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void entityMap() {
|
||||
Map<String, Person> map = new LinkedHashMap<>();
|
||||
map.put("Jane", new Person("Jane"));
|
||||
map.put("Jason", new Person("Jason"));
|
||||
map.put("John", new Person("John"));
|
||||
|
||||
this.client.get().uri("?map=true")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(new ParameterizedTypeReference<Map<String, Person>>() {}).isEqualTo(map);
|
||||
}
|
||||
|
||||
@Test
|
||||
void postEntity() {
|
||||
this.client.post()
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.body(new Person("John"))
|
||||
.exchange()
|
||||
.expectStatus().isCreated()
|
||||
.expectHeader().valueEquals("location", "/persons/John")
|
||||
.expectBody().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/persons")
|
||||
static class PersonController {
|
||||
|
||||
@GetMapping(path = "/{name}", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
Person getPerson(@PathVariable String name) {
|
||||
return new Person(name);
|
||||
}
|
||||
|
||||
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
List<Person> getPersons() {
|
||||
return List.of(new Person("Jane"), new Person("Jason"), new Person("John"));
|
||||
}
|
||||
|
||||
@GetMapping(params = "map", produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
Map<String, Person> getPersonsAsMap() {
|
||||
Map<String, Person> map = new LinkedHashMap<>();
|
||||
map.put("Jane", new Person("Jane"));
|
||||
map.put("Jason", new Person("Jason"));
|
||||
map.put("John", new Person("John"));
|
||||
return map;
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.APPLICATION_JSON_VALUE)
|
||||
ResponseEntity<String> savePerson(@RequestBody Person person) {
|
||||
return ResponseEntity.created(URI.create("/persons/" + person.getName())).build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+330
@@ -0,0 +1,330 @@
|
||||
/*
|
||||
* 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.samples;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import org.springframework.core.ParameterizedTypeReference;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.bind.annotation.RequestHeader;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.DefaultUriBuilderFactory;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests using the {@link RestTestClient} API.
|
||||
*/
|
||||
class RestTestClientTests {
|
||||
|
||||
private RestTestClient client;
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.client = RestTestClient.standaloneSetup(new TestController()).build();
|
||||
}
|
||||
|
||||
@Nested
|
||||
class HttpMethods {
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD"})
|
||||
void testMethod(String method) {
|
||||
RestTestClientTests.this.client.method(HttpMethod.valueOf(method)).uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.method").isEqualTo(method);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGet() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.method").isEqualTo("GET");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPost() {
|
||||
RestTestClientTests.this.client.post().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.method").isEqualTo("POST");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPut() {
|
||||
RestTestClientTests.this.client.put().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.method").isEqualTo("PUT");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDelete() {
|
||||
RestTestClientTests.this.client.delete().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.method").isEqualTo("DELETE");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testPatch() {
|
||||
RestTestClientTests.this.client.patch().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.method").isEqualTo("PATCH");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHead() {
|
||||
RestTestClientTests.this.client.head().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.method").isEqualTo("HEAD");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testOptions() {
|
||||
RestTestClientTests.this.client.options().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectHeader().valueEquals("Allow", "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS")
|
||||
.expectBody().isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
class Mutation {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
RestTestClientTests.this.client.mutate()
|
||||
.apply(builder -> builder.defaultHeader("foo", "bar"))
|
||||
.uriBuilderFactory(new DefaultUriBuilderFactory("/test"))
|
||||
.defaultCookie("foo", "bar")
|
||||
.defaultCookies(cookies -> cookies.add("a", "b"))
|
||||
.defaultHeaders(headers -> headers.set("a", "b"))
|
||||
.build().get()
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.jsonPath("$.uri").isEqualTo("/test")
|
||||
.jsonPath("$.headers.Cookie").isEqualTo("foo=bar; a=b")
|
||||
.jsonPath("$.headers.foo").isEqualTo("bar")
|
||||
.jsonPath("$.headers.a").isEqualTo("b");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class Uris {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.uri").isEqualTo("/test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithPathVariables() {
|
||||
RestTestClientTests.this.client.get().uri("/test/{id}", 1)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.uri").isEqualTo("/test/1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithParameterMap() {
|
||||
RestTestClientTests.this.client.get().uri("/test/{id}", Map.of("id", 1))
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.uri").isEqualTo("/test/1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testWithUrlBuilder() {
|
||||
RestTestClientTests.this.client.get().uri(builder -> builder.path("/test/{id}").build(1))
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.uri").isEqualTo("/test/1");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testURI() {
|
||||
RestTestClientTests.this.client.get().uri(URI.create("/test"))
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.uri").isEqualTo("/test");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class Cookies {
|
||||
@Test
|
||||
void testCookie() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.cookie("foo", "bar")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.headers.Cookie").isEqualTo("foo=bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCookies() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.cookies(cookies -> cookies.add("foo", "bar"))
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.headers.Cookie").isEqualTo("foo=bar");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class Headers {
|
||||
@Test
|
||||
void testHeader() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.header("foo", "bar")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.headers.foo").isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHeaders() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.headers(headers -> headers.set("foo", "bar"))
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.headers.foo").isEqualTo("bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testContentType() {
|
||||
RestTestClientTests.this.client.post().uri("/test")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.headers.Content-Type").isEqualTo("application/json");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAcceptCharset() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.acceptCharset(StandardCharsets.UTF_8)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.headers.Accept-Charset").isEqualTo("utf-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIfModifiedSince() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.ifModifiedSince(ZonedDateTime.of(1970, 1, 1, 0, 0, 0, 0, ZoneId.of("GMT")))
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.headers.If-Modified-Since").isEqualTo("Thu, 01 Jan 1970 00:00:00 GMT");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIfNoneMatch() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.ifNoneMatch("foo")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().jsonPath("$.headers.If-None-Match").isEqualTo("foo");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class Expectations {
|
||||
@Test
|
||||
void testExpectCookie() {
|
||||
RestTestClientTests.this.client.get().uri("/test")
|
||||
.exchange()
|
||||
.expectCookie().value("session", Matchers.equalTo("abc"));
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ReturnResults {
|
||||
@Test
|
||||
void testBodyReturnResult() {
|
||||
var result = RestTestClientTests.this.client.get().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(Map.class).returnResult();
|
||||
assertThat(result.getResponseBody().get("uri")).isEqualTo("/test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReturnResultClass() {
|
||||
var result = RestTestClientTests.this.client.get().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.returnResult(Map.class);
|
||||
assertThat(result.getResponseBody().get("uri")).isEqualTo("/test");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReturnResultParameterizedTypeReference() {
|
||||
var result = RestTestClientTests.this.client.get().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.returnResult(new ParameterizedTypeReference<Map<String, Object>>() {
|
||||
});
|
||||
assertThat(result.getResponseBody().get("uri")).isEqualTo("/test");
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@RequestMapping(path = {"/test", "/test/*"}, produces = "application/json")
|
||||
public Map<String, Object> handle(
|
||||
@RequestHeader HttpHeaders headers,
|
||||
HttpServletRequest request, HttpServletResponse response) {
|
||||
response.addCookie(new Cookie("session", "abc"));
|
||||
return Map.of(
|
||||
"method", request.getMethod(),
|
||||
"uri", request.getRequestURI(),
|
||||
"headers", headers.toSingleValueMap()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.samples;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link RestTestClient} with soft assertions.
|
||||
*
|
||||
*/
|
||||
class SoftAssertionTests {
|
||||
|
||||
private final RestTestClient restTestClient = RestTestClient.standaloneSetup(new TestController()).build();
|
||||
|
||||
|
||||
@Test
|
||||
void expectAll() {
|
||||
this.restTestClient.get().uri("/test").exchange()
|
||||
.expectAll(
|
||||
responseSpec -> responseSpec.expectStatus().isOk(),
|
||||
responseSpec -> responseSpec.expectBody(String.class).isEqualTo("hello")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void expectAllWithMultipleFailures() {
|
||||
assertThatExceptionOfType(AssertionError.class)
|
||||
.isThrownBy(() ->
|
||||
this.restTestClient.get().uri("/test").exchange()
|
||||
.expectAll(
|
||||
responseSpec -> responseSpec.expectStatus().isBadRequest(),
|
||||
responseSpec -> responseSpec.expectStatus().isOk(),
|
||||
responseSpec -> responseSpec.expectBody(String.class).isEqualTo("bogus")
|
||||
)
|
||||
)
|
||||
.withMessage("""
|
||||
Multiple Exceptions (2):
|
||||
Status expected:<400 BAD_REQUEST> but was:<200 OK>
|
||||
Response body expected:<bogus> but was:<hello>""");
|
||||
}
|
||||
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping("/test")
|
||||
String handle() {
|
||||
return "hello";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+196
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* 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.samples;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.xml.bind.annotation.XmlAccessType;
|
||||
import jakarta.xml.bind.annotation.XmlAccessorType;
|
||||
import jakarta.xml.bind.annotation.XmlElement;
|
||||
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
/**
|
||||
* Samples of tests using {@link RestTestClient} with XML content.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class XmlContentTests {
|
||||
|
||||
private static final String persons_XML = """
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<persons>
|
||||
<person><name>Jane</name></person>
|
||||
<person><name>Jason</name></person>
|
||||
<person><name>John</name></person>
|
||||
</persons>
|
||||
""";
|
||||
|
||||
|
||||
private final RestTestClient client = RestTestClient.standaloneSetup(new PersonController()).build();
|
||||
|
||||
|
||||
@Test
|
||||
void xmlContent() {
|
||||
this.client.get().uri("/persons")
|
||||
.accept(MediaType.APPLICATION_XML)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody().xml(persons_XML);
|
||||
}
|
||||
|
||||
@Test
|
||||
void xpathIsEqualTo() {
|
||||
this.client.get().uri("/persons")
|
||||
.accept(MediaType.APPLICATION_XML)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.xpath("/").exists()
|
||||
.xpath("/persons").exists()
|
||||
.xpath("/persons/person").exists()
|
||||
.xpath("/persons/person").nodeCount(3)
|
||||
.xpath("/persons/person[1]/name").isEqualTo("Jane")
|
||||
.xpath("/persons/person[2]/name").isEqualTo("Jason")
|
||||
.xpath("/persons/person[3]/name").isEqualTo("John");
|
||||
}
|
||||
|
||||
@Test
|
||||
void xpathDoesNotExist() {
|
||||
this.client.get().uri("/persons")
|
||||
.accept(MediaType.APPLICATION_XML)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.xpath("/persons/person[4]").doesNotExist();
|
||||
}
|
||||
|
||||
@Test
|
||||
void xpathNodeCount() {
|
||||
this.client.get().uri("/persons")
|
||||
.accept(MediaType.APPLICATION_XML)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.xpath("/persons/person").nodeCount(3)
|
||||
.xpath("/persons/person").nodeCount(equalTo(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
void xpathMatches() {
|
||||
this.client.get().uri("/persons")
|
||||
.accept(MediaType.APPLICATION_XML)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.xpath("//person/name").string(startsWith("J"))
|
||||
.xpath("//person/name").string(s -> {
|
||||
if (!s.startsWith("J")) {
|
||||
throw new AssertionError("Name does not start with J: " + s);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void xpathContainsSubstringViaRegex() {
|
||||
this.client.get().uri("/persons/John")
|
||||
.accept(MediaType.APPLICATION_XML)
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody()
|
||||
.xpath("//name[contains(text(), 'oh')]").exists();
|
||||
}
|
||||
|
||||
@Test
|
||||
void postXmlContent() {
|
||||
String content =
|
||||
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>" +
|
||||
"<person><name>John</name></person>";
|
||||
|
||||
this.client.post().uri("/persons")
|
||||
.contentType(MediaType.APPLICATION_XML)
|
||||
.body(content)
|
||||
.exchange()
|
||||
.expectStatus().isCreated()
|
||||
.expectHeader().valueEquals(HttpHeaders.LOCATION, "/persons/John")
|
||||
.expectBody().isEmpty();
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@XmlRootElement(name="persons")
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
private static class PersonsWrapper {
|
||||
|
||||
@XmlElement(name="person")
|
||||
private final List<Person> persons = new ArrayList<>();
|
||||
|
||||
public PersonsWrapper() {
|
||||
}
|
||||
|
||||
public PersonsWrapper(List<Person> persons) {
|
||||
this.persons.addAll(persons);
|
||||
}
|
||||
|
||||
public PersonsWrapper(Person... persons) {
|
||||
this.persons.addAll(Arrays.asList(persons));
|
||||
}
|
||||
|
||||
public List<Person> getpersons() {
|
||||
return this.persons;
|
||||
}
|
||||
}
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/persons")
|
||||
static class PersonController {
|
||||
|
||||
@GetMapping(produces = MediaType.APPLICATION_XML_VALUE)
|
||||
PersonsWrapper getPersons() {
|
||||
return new PersonsWrapper(new Person("Jane"), new Person("Jason"), new Person("John"));
|
||||
}
|
||||
|
||||
@GetMapping(path = "/{name}", produces = MediaType.APPLICATION_XML_VALUE)
|
||||
Person getPerson(@PathVariable String name) {
|
||||
return new Person(name);
|
||||
}
|
||||
|
||||
@PostMapping(consumes = MediaType.APPLICATION_XML_VALUE)
|
||||
ResponseEntity<Object> savepersons(@RequestBody Person person) {
|
||||
URI location = URI.create(String.format("/persons/%s", person.getName()));
|
||||
return ResponseEntity.created(location).build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.samples.bind;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
/**
|
||||
* Sample tests demonstrating "mock" server tests binding to server infrastructure
|
||||
* declared in a Spring ApplicationContext.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
@SpringJUnitWebConfig(ApplicationContextTests.WebConfig.class)
|
||||
class ApplicationContextTests {
|
||||
|
||||
private RestTestClient client;
|
||||
private final WebApplicationContext context;
|
||||
|
||||
public ApplicationContextTests(WebApplicationContext context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.client = RestTestClient.bindToApplicationContext(context).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
this.client.get().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("It works!");
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class WebConfig {
|
||||
|
||||
@Bean
|
||||
public TestController controller() {
|
||||
return new TestController();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping("/test")
|
||||
public String handle() {
|
||||
return "It works!";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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.samples.bind;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Sample tests demonstrating "mock" server tests binding to an annotated
|
||||
* controller.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class ControllerTests {
|
||||
|
||||
private RestTestClient client;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
this.client = RestTestClient.standaloneSetup(new TestController()).build();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
this.client.get().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("It works!");
|
||||
}
|
||||
|
||||
|
||||
@RestController
|
||||
static class TestController {
|
||||
|
||||
@GetMapping("/test")
|
||||
public String handle() {
|
||||
return "It works!";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.samples.bind;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpFilter;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.servlet.function.ServerResponse;
|
||||
|
||||
import static org.springframework.http.HttpStatus.I_AM_A_TEAPOT;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for a {@link Filter}.
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class FilterTests {
|
||||
|
||||
@Test
|
||||
void filter() {
|
||||
|
||||
Filter filter = new HttpFilter() {
|
||||
@Override
|
||||
protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
|
||||
res.getWriter().write("It works!");
|
||||
}
|
||||
};
|
||||
|
||||
RestTestClient client = RestTestClient.bindToRouterFunction(
|
||||
request -> Optional.of(req -> ServerResponse.status(I_AM_A_TEAPOT).build()))
|
||||
.configureServer(builder -> builder.addFilters(filter))
|
||||
.build();
|
||||
|
||||
client.get().uri("/")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("It works!");
|
||||
}
|
||||
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.samples.bind;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.http.server.reactive.HttpHandler;
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.reactive.function.server.RouterFunctions;
|
||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
||||
import org.springframework.web.testfixture.http.server.reactive.bootstrap.ReactorHttpServer;
|
||||
|
||||
import static org.springframework.web.reactive.function.server.RequestPredicates.GET;
|
||||
import static org.springframework.web.reactive.function.server.RouterFunctions.route;
|
||||
|
||||
/**
|
||||
* Sample tests demonstrating live server integration tests.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class HttpServerTests {
|
||||
|
||||
private ReactorHttpServer server;
|
||||
|
||||
private RestTestClient client;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void start() throws Exception {
|
||||
HttpHandler httpHandler = RouterFunctions.toHttpHandler(
|
||||
route(GET("/test"), request -> ServerResponse.ok().bodyValue("It works!")));
|
||||
|
||||
this.server = new ReactorHttpServer();
|
||||
this.server.setHandler(httpHandler);
|
||||
this.server.afterPropertiesSet();
|
||||
this.server.start();
|
||||
|
||||
this.client = RestTestClient.bindToServer()
|
||||
.baseUrl("http://localhost:" + this.server.getPort())
|
||||
.build();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void stop() {
|
||||
this.server.stop();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
this.client.get().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("It works!");
|
||||
}
|
||||
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.samples.bind;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.test.web.servlet.client.RestTestClient;
|
||||
import org.springframework.web.servlet.function.RouterFunction;
|
||||
import org.springframework.web.servlet.function.ServerResponse;
|
||||
|
||||
import static org.springframework.web.servlet.function.RequestPredicates.GET;
|
||||
import static org.springframework.web.servlet.function.RouterFunctions.route;
|
||||
|
||||
/**
|
||||
* Sample tests demonstrating "mock" server tests binding to a RouterFunction.
|
||||
*
|
||||
* @author Rob Worsnop
|
||||
*/
|
||||
class RouterFunctionTests {
|
||||
|
||||
private RestTestClient testClient;
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws Exception {
|
||||
|
||||
RouterFunction<?> route = route(GET("/test"), request ->
|
||||
ServerResponse.ok().body("It works!"));
|
||||
|
||||
this.testClient = RestTestClient.bindToRouterFunction(route).build();
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() throws Exception {
|
||||
this.testClient.get().uri("/test")
|
||||
.exchange()
|
||||
.expectStatus().isOk()
|
||||
.expectBody(String.class).isEqualTo("It works!");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user