Polishing contribution

Closes gh-27280
This commit is contained in:
rstoyanchev 2022-09-27 17:08:52 +01:00
parent d14477eb84
commit b1ee44f12e
3 changed files with 57 additions and 74 deletions

View File

@ -20,10 +20,6 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;
@ -84,6 +80,7 @@ public class DefaultResponseCreator implements ResponseCreator {
/** /**
* Set the body from a string using the given character set. * Set the body from a string using the given character set.
* @since 6.0
*/ */
public DefaultResponseCreator body(String content, Charset charset) { public DefaultResponseCreator body(String content, Charset charset) {
this.content = content.getBytes(charset); this.content = content.getBytes(charset);
@ -123,22 +120,13 @@ public class DefaultResponseCreator implements ResponseCreator {
} }
/** /**
* Add a single header. * Add a response header with one or more values.
* @since 6.0
*/ */
public DefaultResponseCreator header(String name, String value) { public DefaultResponseCreator header(String name, String ... headerValues) {
// This is really just an alias, but it makes the interface more fluent. for (String headerValue : headerValues) {
return headers(name, value); this.headers.add(name, headerValue);
} }
/**
* Add one or more headers.
*/
public DefaultResponseCreator headers(String name, String ... value) {
List<String> valueList = Stream.of(value)
.filter(Objects::nonNull)
.collect(Collectors.toList());
this.headers.addAll(name, valueList);
return this; return this;
} }
@ -150,34 +138,23 @@ public class DefaultResponseCreator implements ResponseCreator {
return this; return this;
} }
/**
* Add a single cookie.
*/
public DefaultResponseCreator cookie(ResponseCookie cookie) {
// This is really just an alias, but it makes the interface more fluent.
return cookies(cookie);
}
/** /**
* Add one or more cookies. * Add one or more cookies.
* @since 6.0
*/ */
public DefaultResponseCreator cookies(ResponseCookie... cookies) { public DefaultResponseCreator cookies(ResponseCookie... cookies) {
for (ResponseCookie cookie : cookies) { for (ResponseCookie cookie : cookies) {
this.headers.add(HttpHeaders.SET_COOKIE, cookie.toString()); this.headers.add(HttpHeaders.SET_COOKIE, cookie.toString());
} }
return this; return this;
} }
/** /**
* Copy all given cookies. * Copy all cookies from the given {@link MultiValueMap}.
* @since 6.0
*/ */
public DefaultResponseCreator cookies(MultiValueMap<String, ResponseCookie> cookies) { public DefaultResponseCreator cookies(MultiValueMap<String, ResponseCookie> multiValueMap) {
cookies.values() multiValueMap.values().forEach(cookies -> cookies.forEach(this::cookies));
.stream()
.flatMap(List::stream)
.forEach(cookie -> this.headers.add(HttpHeaders.SET_COOKIE, cookie.toString()));
return this; return this;
} }

View File

@ -85,6 +85,7 @@ public abstract class MockRestResponseCreators {
/** /**
* {@code ResponseCreator} for a 202 response (ACCEPTED). * {@code ResponseCreator} for a 202 response (ACCEPTED).
* @since 6.0
*/ */
public static DefaultResponseCreator withAccepted() { public static DefaultResponseCreator withAccepted() {
return new DefaultResponseCreator(HttpStatus.ACCEPTED); return new DefaultResponseCreator(HttpStatus.ACCEPTED);
@ -113,6 +114,7 @@ public abstract class MockRestResponseCreators {
/** /**
* {@code ResponseCreator} for a 403 response (FORBIDDEN). * {@code ResponseCreator} for a 403 response (FORBIDDEN).
* @since 6.0
*/ */
public static DefaultResponseCreator withForbiddenRequest() { public static DefaultResponseCreator withForbiddenRequest() {
return new DefaultResponseCreator(HttpStatus.FORBIDDEN); return new DefaultResponseCreator(HttpStatus.FORBIDDEN);
@ -120,6 +122,7 @@ public abstract class MockRestResponseCreators {
/** /**
* {@code ResponseCreator} for a 404 response (NOT_FOUND). * {@code ResponseCreator} for a 404 response (NOT_FOUND).
* @since 6.0
*/ */
public static DefaultResponseCreator withResourceNotFound() { public static DefaultResponseCreator withResourceNotFound() {
return new DefaultResponseCreator(HttpStatus.NOT_FOUND); return new DefaultResponseCreator(HttpStatus.NOT_FOUND);
@ -127,6 +130,7 @@ public abstract class MockRestResponseCreators {
/** /**
* {@code ResponseCreator} for a 409 response (CONFLICT). * {@code ResponseCreator} for a 409 response (CONFLICT).
* @since 6.0
*/ */
public static DefaultResponseCreator withRequestConflict() { public static DefaultResponseCreator withRequestConflict() {
return new DefaultResponseCreator(HttpStatus.CONFLICT); return new DefaultResponseCreator(HttpStatus.CONFLICT);
@ -134,14 +138,16 @@ public abstract class MockRestResponseCreators {
/** /**
* {@code ResponseCreator} for a 429 ratelimited response (TOO_MANY_REQUESTS). * {@code ResponseCreator} for a 429 ratelimited response (TOO_MANY_REQUESTS).
* @since 6.0
*/ */
public static DefaultResponseCreator withTooManyRequests() { public static DefaultResponseCreator withTooManyRequests() {
return new DefaultResponseCreator(HttpStatus.TOO_MANY_REQUESTS); return new DefaultResponseCreator(HttpStatus.TOO_MANY_REQUESTS);
} }
/** /**
* {@code ResponseCreator} for a 429 ratelimited response (TOO_MANY_REQUESTS) with a {@code Retry-After} header * {@code ResponseCreator} for a 429 rate-limited response (TOO_MANY_REQUESTS)
* in seconds. * with a {@code Retry-After} header in seconds.
* @since 6.0
*/ */
public static DefaultResponseCreator withTooManyRequests(int retryAfter) { public static DefaultResponseCreator withTooManyRequests(int retryAfter) {
return new DefaultResponseCreator(HttpStatus.TOO_MANY_REQUESTS) return new DefaultResponseCreator(HttpStatus.TOO_MANY_REQUESTS)
@ -157,6 +163,7 @@ public abstract class MockRestResponseCreators {
/** /**
* {@code ResponseCreator} for a 502 response (BAD_GATEWAY). * {@code ResponseCreator} for a 502 response (BAD_GATEWAY).
* @since 6.0
*/ */
public static DefaultResponseCreator withBadGateway() { public static DefaultResponseCreator withBadGateway() {
return new DefaultResponseCreator(HttpStatus.BAD_GATEWAY); return new DefaultResponseCreator(HttpStatus.BAD_GATEWAY);
@ -164,6 +171,7 @@ public abstract class MockRestResponseCreators {
/** /**
* {@code ResponseCreator} for a 503 response (SERVICE_UNAVAILABLE). * {@code ResponseCreator} for a 503 response (SERVICE_UNAVAILABLE).
* @since 6.0
*/ */
public static DefaultResponseCreator withServiceUnavailable() { public static DefaultResponseCreator withServiceUnavailable() {
return new DefaultResponseCreator(HttpStatus.SERVICE_UNAVAILABLE); return new DefaultResponseCreator(HttpStatus.SERVICE_UNAVAILABLE);
@ -171,6 +179,7 @@ public abstract class MockRestResponseCreators {
/** /**
* {@code ResponseCreator} for a 504 response (GATEWAY_TIMEOUT). * {@code ResponseCreator} for a 504 response (GATEWAY_TIMEOUT).
* @since 6.0
*/ */
public static DefaultResponseCreator withGatewayTimeout() { public static DefaultResponseCreator withGatewayTimeout() {
return new DefaultResponseCreator(HttpStatus.GATEWAY_TIMEOUT); return new DefaultResponseCreator(HttpStatus.GATEWAY_TIMEOUT);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2021 the original author or authors. * Copyright 2002-2022 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -52,23 +52,25 @@ import static org.mockito.Mockito.mock;
* Tests for the {@link DefaultResponseCreator} factory methods. * Tests for the {@link DefaultResponseCreator} factory methods.
* *
* @author Ashley Scopes * @author Ashley Scopes
* @author Rossen Stoyanchev
*/ */
class DefaultResponseCreatorTests { class DefaultResponseCreatorTests {
@ParameterizedTest(name = "expect status to be set [{0}]") @ParameterizedTest(name = "expect status to be set [{0}]")
@ValueSource(ints = {200, 401, 429}) @ValueSource(ints = {200, 401, 429})
void expectStatus(int statusValue) throws IOException { void expectStatus(int statusValue) throws IOException {
HttpStatus status = HttpStatus.valueOf(statusValue); HttpStatus status = HttpStatus.valueOf(statusValue);
ClientHttpResponse response = createResponse(new DefaultResponseCreator(status)); DefaultResponseCreator creator = new DefaultResponseCreator(status);
assertThat(response.getStatusCode()).isEqualTo(status);
assertThat(createResponse(creator).getStatusCode()).isEqualTo(status);
} }
@Test @Test
void setBodyFromString() throws IOException { void setBodyFromString() throws IOException {
// Use unicode codepoint for "thinking" emoji to help verify correct encoding is used internally. // Use unicode codepoint for "thinking" emoji to help verify correct encoding is used internally.
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK) DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK).body("hello, world! \uD83E\uDD14");
.body("hello, world! \uD83E\uDD14"));
assertThat(IOUtils.toByteArray(response.getBody())) assertThat(IOUtils.toByteArray(createResponse(creator).getBody()))
.isEqualTo("hello, world! \uD83E\uDD14".getBytes(StandardCharsets.UTF_8)); .isEqualTo("hello, world! \uD83E\uDD14".getBytes(StandardCharsets.UTF_8));
} }
@ -81,68 +83,62 @@ class DefaultResponseCreatorTests {
.isTrue(); .isTrue();
Charset charsetObj = Charset.forName(charset); Charset charsetObj = Charset.forName(charset);
String content = "hello! €½$~@><·─"; String content = "hello! €½$~@><·─";
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK) DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK).body(content, charsetObj);
.body(content, charsetObj));
ByteBuffer expectBuff = charsetObj.encode(content); ByteBuffer expectBuff = charsetObj.encode(content);
byte[] expect = new byte[expectBuff.remaining()]; byte[] expect = new byte[expectBuff.remaining()];
expectBuff.get(expect); expectBuff.get(expect);
assertThat(IOUtils.toByteArray(response.getBody())).isEqualTo(expect); assertThat(IOUtils.toByteArray(createResponse(creator).getBody())).isEqualTo(expect);
} }
@Test @Test
void setBodyFromByteArray() throws IOException { void setBodyFromByteArray() throws IOException {
byte[] body = { 0, 9, 18, 27, 36, 45, 54, 63, 72, 81, 90 }; byte[] body = { 0, 9, 18, 27, 36, 45, 54, 63, 72, 81, 90 };
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK).body(body)); DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK).body(body);
assertThat(IOUtils.toByteArray(response.getBody())).isEqualTo(body);
assertThat(IOUtils.toByteArray(createResponse(creator).getBody())).isEqualTo(body);
} }
@Test @Test
void setBodyFromResource() throws IOException { void setBodyFromResource() throws IOException {
byte[] resourceContent = {7, 14, 21, 28, 35}; byte[] resourceContent = {7, 14, 21, 28, 35};
Resource resource = mock(Resource.class); Resource resource = mock(Resource.class);
given(resource.getInputStream()).willReturn(new ByteArrayInputStream(resourceContent)); given(resource.getInputStream()).willReturn(new ByteArrayInputStream(resourceContent));
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK).body(resource)); ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK).body(resource));
then(resource).should().getInputStream(); then(resource).should().getInputStream();
assertThat(IOUtils.toByteArray(response.getBody())).isEqualTo(resourceContent); assertThat(IOUtils.toByteArray(response.getBody())).isEqualTo(resourceContent);
} }
@Test @Test
void setContentType() throws IOException { void setContentType() throws IOException {
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK) MediaType mediaType = MediaType.APPLICATION_JSON;
.contentType(MediaType.APPLICATION_JSON)); DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK).contentType(mediaType);
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); assertThat(createResponse(creator).getHeaders().getContentType()).isEqualTo(mediaType);
} }
@Test @Test
void setLocation() throws IOException { void setLocation() throws IOException {
URI uri = UriComponentsBuilder URI uri = URI.create("https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html");
.fromUriString("https://docs.spring.io/spring-framework/docs/current/reference/html/testing.html") DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK).location(uri);
.build()
.toUri();
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK).location(uri)); assertThat(createResponse(creator).getHeaders().getLocation()).isEqualTo(uri);
assertThat(response.getHeaders().getLocation()).isEqualTo(uri);
} }
@Test @Test
void setHeader() throws IOException { void setHeader() throws IOException {
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK) DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK)
.header("foo", "bar") .header("foo", "bar")
.header("baz", "bork") .header("baz", "bork")
.headers("lorem", "ipsum", "dolor", "sit", "amet")); .header("lorem", "ipsum", "dolor", "sit", "amet");
HttpHeaders headers = response.getHeaders(); HttpHeaders headers = createResponse(creator).getHeaders();
assertThat(headers.get("foo")).isNotNull().isEqualTo(Collections.singletonList("bar")); assertThat(headers.get("foo")).isNotNull().isEqualTo(Collections.singletonList("bar"));
assertThat(headers.get("baz")).isNotNull().isEqualTo(Collections.singletonList("bork")); assertThat(headers.get("baz")).isNotNull().isEqualTo(Collections.singletonList("bork"));
assertThat(headers.get("lorem")).isNotNull().isEqualTo(Arrays.asList("ipsum", "dolor", "sit", "amet")); assertThat(headers.get("lorem")).isNotNull().isEqualTo(Arrays.asList("ipsum", "dolor", "sit", "amet"));
@ -158,11 +154,11 @@ class DefaultResponseCreatorTests {
HttpHeaders secondHeaders = new HttpHeaders(); HttpHeaders secondHeaders = new HttpHeaders();
secondHeaders.setAllow(Collections.singleton(HttpMethod.PUT)); secondHeaders.setAllow(Collections.singleton(HttpMethod.PUT));
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK) DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK)
.headers(firstHeaders) .headers(firstHeaders)
.headers(secondHeaders)); .headers(secondHeaders);
HttpHeaders responseHeaders = response.getHeaders(); HttpHeaders responseHeaders = createResponse(creator).getHeaders();
assertThat(responseHeaders.getContentType()).isEqualTo(MediaType.APPLICATION_JSON); assertThat(responseHeaders.getContentType()).isEqualTo(MediaType.APPLICATION_JSON);
assertThat(responseHeaders.getOrigin()).isEqualTo("https://github.com"); assertThat(responseHeaders.getOrigin()).isEqualTo("https://github.com");
@ -176,12 +172,12 @@ class DefaultResponseCreatorTests {
ResponseCookie thirdCookie = ResponseCookie.from("cookie-cookie", "cookies").build(); ResponseCookie thirdCookie = ResponseCookie.from("cookie-cookie", "cookies").build();
ResponseCookie fourthCookie = ResponseCookie.from("foobar", "bazbork").build(); ResponseCookie fourthCookie = ResponseCookie.from("foobar", "bazbork").build();
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK) DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK)
.cookie(firstCookie) .cookies(firstCookie)
.cookie(secondCookie) .cookies(secondCookie)
.cookies(thirdCookie, fourthCookie)); .cookies(thirdCookie, fourthCookie);
HttpHeaders responseHeaders = response.getHeaders(); HttpHeaders responseHeaders = createResponse(creator).getHeaders();
assertThat(responseHeaders.get(HttpHeaders.SET_COOKIE)) assertThat(responseHeaders.get(HttpHeaders.SET_COOKIE))
.isNotNull() .isNotNull()
@ -207,11 +203,11 @@ class DefaultResponseCreatorTests {
firstCookies.add(thirdCookie.getName(), thirdCookie); firstCookies.add(thirdCookie.getName(), thirdCookie);
firstCookies.add(fourthCookie.getName(), fourthCookie); firstCookies.add(fourthCookie.getName(), fourthCookie);
ClientHttpResponse response = createResponse(new DefaultResponseCreator(HttpStatus.OK) DefaultResponseCreator creator = new DefaultResponseCreator(HttpStatus.OK)
.cookies(firstCookies) .cookies(firstCookies)
.cookies(secondCookies)); .cookies(secondCookies);
HttpHeaders responseHeaders = response.getHeaders(); HttpHeaders responseHeaders = createResponse(creator).getHeaders();
assertThat(responseHeaders.get(HttpHeaders.SET_COOKIE)) assertThat(responseHeaders.get(HttpHeaders.SET_COOKIE))
.isNotNull() .isNotNull()
@ -227,4 +223,5 @@ class DefaultResponseCreatorTests {
URI uri = UriComponentsBuilder.fromUriString("/foo/bar").build().toUri(); URI uri = UriComponentsBuilder.fromUriString("/foo/bar").build().toUri();
return creator.createResponse(new MockClientHttpRequest(HttpMethod.POST, uri)); return creator.createResponse(new MockClientHttpRequest(HttpMethod.POST, uri));
} }
} }