From b0db2ddbb2f8d135a5c7b6fd872dfa79cd4a83f1 Mon Sep 17 00:00:00 2001 From: Paul Boutes Date: Thu, 17 May 2018 23:03:00 +0200 Subject: [PATCH] Mock: manage headers using RequestHeaders (#706) * feat(feign-mock): add RequestHeaders class to manage headers * feat(feign-mock): use google code style formatting * feat(feign-mock): remove system.out * feat(RequestKey): add deprecated headers builder + format code * feat(feign-mock): format pom correctly * feat(feign-mock): format pom correctly * fix(feign-mock): undo some typo and no-op change --- mock/src/main/java/feign/mock/MockClient.java | 5 +- .../main/java/feign/mock/RequestHeaders.java | 119 ++++++++++++++++++ mock/src/main/java/feign/mock/RequestKey.java | 37 ++++-- .../feign/mock/MockClientSequentialTest.java | 12 +- .../test/java/feign/mock/MockClientTest.java | 1 - .../test/java/feign/mock/MockTargetTest.java | 2 +- .../java/feign/mock/RequestHeadersTest.java | 82 ++++++++++++ .../test/java/feign/mock/RequestKeyTest.java | 30 +++-- 8 files changed, 249 insertions(+), 39 deletions(-) create mode 100644 mock/src/main/java/feign/mock/RequestHeaders.java create mode 100644 mock/src/test/java/feign/mock/RequestHeadersTest.java diff --git a/mock/src/main/java/feign/mock/MockClient.java b/mock/src/main/java/feign/mock/MockClient.java index 381b9e690..b0cb98195 100644 --- a/mock/src/main/java/feign/mock/MockClient.java +++ b/mock/src/main/java/feign/mock/MockClient.java @@ -24,7 +24,6 @@ import java.net.HttpURLConnection; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; @@ -45,8 +44,6 @@ public RequestResponse(RequestKey requestKey, Response.Builder responseBuilder) } } - public static final Map> EMPTY_HEADERS = Collections.emptyMap(); - private final List responses = new ArrayList(); private final Map> requests = new HashMap>(); @@ -201,7 +198,7 @@ public MockClient add(RequestKey requestKey, int status, byte[] responseBody) { Response.builder() .status(status) .reason("Mocked") - .headers(EMPTY_HEADERS) + .headers(RequestHeaders.EMPTY) .body(responseBody)); } diff --git a/mock/src/main/java/feign/mock/RequestHeaders.java b/mock/src/main/java/feign/mock/RequestHeaders.java new file mode 100644 index 000000000..ce7c23170 --- /dev/null +++ b/mock/src/main/java/feign/mock/RequestHeaders.java @@ -0,0 +1,119 @@ +/** + * Copyright 2012-2018 The Feign 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 + * + *

http://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 feign.mock; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class RequestHeaders { + + public static class Builder { + + private Map> headers = new HashMap>(); + + private Builder() {} + + public Builder add(String key, Collection values) { + if (!headers.containsKey(key)) { + headers.put(key, values); + } else { + Collection previousValues = headers.get(key); + previousValues.addAll(values); + headers.put(key, previousValues); + } + return this; + } + + public Builder add(String key, String value) { + if (!headers.containsKey(key)) { + headers.put(key, new ArrayList(Arrays.asList(value))); + } else { + final Collection values = headers.get(key); + values.add(value); + headers.put(key, values); + } + return this; + } + + public RequestHeaders build() { + return new RequestHeaders(this); + } + } + + public static final Map> EMPTY = Collections.emptyMap(); + + public static Builder builder() { + return new Builder(); + } + + public static RequestHeaders of(Map> headers) { + return new RequestHeaders(headers); + } + + private Map> headers; + + private RequestHeaders(Builder builder) { + this.headers = builder.headers; + } + + private RequestHeaders(Map> headers) { + this.headers = headers; + } + + public int size() { + return headers.size(); + } + + public int sizeOf(String key) { + if (!headers.containsKey(key)) { + return 0; + } + return headers.get(key).size(); + } + + public Collection fetch(String key) { + return headers.get(key); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final RequestHeaders other = (RequestHeaders) obj; + return this.headers.equals(other.headers); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + for (Map.Entry> entry : headers.entrySet()) { + builder.append(entry).append(',').append(' '); + } + if (builder.length() > 0) { + return builder.substring(0, builder.length() - 2); + } + return "no"; + } +} diff --git a/mock/src/main/java/feign/mock/RequestKey.java b/mock/src/main/java/feign/mock/RequestKey.java index f73244a90..8a60679d3 100644 --- a/mock/src/main/java/feign/mock/RequestKey.java +++ b/mock/src/main/java/feign/mock/RequestKey.java @@ -32,7 +32,7 @@ public static class Builder { private final String url; - private Map> headers; + private RequestHeaders headers; private Charset charset; @@ -43,7 +43,13 @@ private Builder(HttpMethod method, String url) { this.url = url; } + @Deprecated public Builder headers(Map> headers) { + this.headers = RequestHeaders.of(headers); + return this; + } + + public Builder headers(RequestHeaders headers) { this.headers = headers; return this; } @@ -87,7 +93,7 @@ private static String buildUrl(Request request) { private final String url; - private final Map> headers; + private final RequestHeaders headers; private final Charset charset; @@ -104,7 +110,7 @@ private RequestKey(Builder builder) { private RequestKey(Request request) { this.method = HttpMethod.valueOf(request.method()); this.url = buildUrl(request); - this.headers = request.headers(); + this.headers = RequestHeaders.of(request.headers()); this.charset = request.charset(); this.body = request.body(); } @@ -117,7 +123,7 @@ public String getUrl() { return url; } - public Map> getHeaders() { + public RequestHeaders getHeaders() { return headers; } @@ -140,15 +146,22 @@ public int hashCode() { @Override public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (getClass() != obj.getClass()) return false; + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } final RequestKey other = (RequestKey) obj; - if (method != other.method) return false; + if (method != other.method) { + return false; + } if (url == null) { - if (other.url != null) return false; - } else if (!url.equals(other.url)) return false; - return true; + return other.url == null; + } else return url.equals(other.url); } public boolean equalsExtended(Object obj) { @@ -170,7 +183,7 @@ public String toString() { "Request [%s %s: %s headers and %s]", method, url, - headers == null ? "without" : "with " + headers.size(), + headers == null ? "without" : "with " + headers, charset == null ? "no charset" : "charset " + charset); } } diff --git a/mock/src/test/java/feign/mock/MockClientSequentialTest.java b/mock/src/test/java/feign/mock/MockClientSequentialTest.java index 3ac43a4d8..dc64cef19 100644 --- a/mock/src/test/java/feign/mock/MockClientSequentialTest.java +++ b/mock/src/test/java/feign/mock/MockClientSequentialTest.java @@ -24,6 +24,7 @@ import feign.Body; import feign.Feign; import feign.FeignException; +import feign.Headers; import feign.Param; import feign.RequestLine; import feign.Response; @@ -43,6 +44,7 @@ public class MockClientSequentialTest { interface GitHub { + @Headers({"Name: {owner}"}) @RequestLine("GET /repos/{owner}/{repo}/contributors") List contributors(@Param("owner") String owner, @Param("repo") String repo); @@ -89,14 +91,13 @@ public Object decode(Response response, Type type) } private GitHub githubSequential; - private MockClient mockClientSequential; @Before public void setup() throws IOException { try (InputStream input = getClass().getResourceAsStream("/fixtures/contributors.json")) { byte[] data = toByteArray(input); - + RequestHeaders headers = RequestHeaders.builder().add("Name", "netflix").build(); mockClientSequential = new MockClient(true); githubSequential = Feign.builder() @@ -104,8 +105,9 @@ public void setup() throws IOException { .client( mockClientSequential .add( - HttpMethod.GET, - "/repos/netflix/feign/contributors", + RequestKey.builder(HttpMethod.GET, "/repos/netflix/feign/contributors") + .headers(headers) + .build(), HttpsURLConnection.HTTP_OK, data) .add( @@ -122,7 +124,7 @@ public void setup() throws IOException { "/repos/netflix/feign/contributors", Response.builder() .status(HttpsURLConnection.HTTP_OK) - .headers(MockClient.EMPTY_HEADERS) + .headers(RequestHeaders.EMPTY) .body(data))) .target(new MockTarget<>(GitHub.class)); } diff --git a/mock/src/test/java/feign/mock/MockClientTest.java b/mock/src/test/java/feign/mock/MockClientTest.java index f4b0457cd..53c301841 100644 --- a/mock/src/test/java/feign/mock/MockClientTest.java +++ b/mock/src/test/java/feign/mock/MockClientTest.java @@ -91,7 +91,6 @@ public Object decode(Response response, Type type) } private GitHub github; - private MockClient mockClient; @Before diff --git a/mock/src/test/java/feign/mock/MockTargetTest.java b/mock/src/test/java/feign/mock/MockTargetTest.java index 989c9b70c..9ac34a649 100644 --- a/mock/src/test/java/feign/mock/MockTargetTest.java +++ b/mock/src/test/java/feign/mock/MockTargetTest.java @@ -14,7 +14,7 @@ package feign.mock; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.*; +import static org.junit.Assert.assertThat; import org.junit.Before; import org.junit.Test; diff --git a/mock/src/test/java/feign/mock/RequestHeadersTest.java b/mock/src/test/java/feign/mock/RequestHeadersTest.java new file mode 100644 index 000000000..8372a462a --- /dev/null +++ b/mock/src/test/java/feign/mock/RequestHeadersTest.java @@ -0,0 +1,82 @@ +/** + * Copyright 2012-2018 The Feign 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 + * + *

http://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 feign.mock; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; + +public class RequestHeadersTest { + + @Test + public void shouldCreateEmptyRequestHeaders() { + RequestHeaders headers = RequestHeaders.builder().build(); + assertThat(headers.size()).isEqualTo(0); + } + + @Test + public void shouldReturnZeroSizeForUnknownKey() { + RequestHeaders headers = RequestHeaders.builder().build(); + assertThat(headers.sizeOf("unknown")).isEqualTo(0); + } + + @Test + public void shouldCreateRequestHeadersFromSingleValue() { + RequestHeaders headers = + RequestHeaders.builder().add("header", "val").add("other header", "val2").build(); + + assertThat(headers.fetch("header")).contains("val"); + assertThat(headers.sizeOf("header")).isEqualTo(1); + assertThat(headers.fetch("other header")).contains("val2"); + assertThat(headers.sizeOf("other header")).isEqualTo(1); + } + + @Test + public void shouldCreateRequestHeadersFromSingleValueAndCollection() { + RequestHeaders headers = + RequestHeaders.builder() + .add("header", "val") + .add("other header", "val2") + .add("header", Arrays.asList("val3", "val4")) + .build(); + + assertThat(headers.fetch("header")).contains("val", "val3", "val4"); + assertThat(headers.sizeOf("header")).isEqualTo(3); + assertThat(headers.fetch("other header")).contains("val2"); + assertThat(headers.sizeOf("other header")).isEqualTo(1); + } + + @Test + public void shouldCreateRequestHeadersFromHeadersMap() { + Map> map = new HashMap>(); + map.put("header", Arrays.asList("val", "val2")); + RequestHeaders headers = RequestHeaders.of(map); + assertThat(headers.size()).isEqualTo(1); + } + + @Test + public void shouldPrintHeaders() { + RequestHeaders headers = + RequestHeaders.builder() + .add("header", "val") + .add("other header", "val2") + .add("header", Arrays.asList("val3", "val4")) + .build(); + assertThat(headers.toString()).isEqualTo("other header=[val2], header=[val, val3, val4]"); + } +} diff --git a/mock/src/test/java/feign/mock/RequestKeyTest.java b/mock/src/test/java/feign/mock/RequestKeyTest.java index b40cb91f5..42643f85c 100644 --- a/mock/src/test/java/feign/mock/RequestKeyTest.java +++ b/mock/src/test/java/feign/mock/RequestKeyTest.java @@ -16,7 +16,7 @@ import static org.hamcrest.Matchers.both; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.startsWith; import static org.junit.Assert.assertThat; @@ -36,11 +36,10 @@ public class RequestKeyTest { @Before public void setUp() { - Map> map = new HashMap<>(); - map.put("my-header", Arrays.asList("val")); + RequestHeaders headers = RequestHeaders.builder().add("my-header", "val").build(); requestKey = RequestKey.builder(HttpMethod.GET, "a") - .headers(map) + .headers(headers) .charset(StandardCharsets.UTF_16) .body("content") .build(); @@ -50,16 +49,16 @@ public void setUp() { public void builder() throws Exception { assertThat(requestKey.getMethod(), equalTo(HttpMethod.GET)); assertThat(requestKey.getUrl(), equalTo("a")); - assertThat(requestKey.getHeaders().entrySet(), hasSize(1)); + assertThat(requestKey.getHeaders().size(), is(1)); assertThat( - requestKey.getHeaders().get("my-header"), + requestKey.getHeaders().fetch("my-header"), equalTo((Collection) Arrays.asList("val"))); assertThat(requestKey.getCharset(), equalTo(StandardCharsets.UTF_16)); } @Test public void create() throws Exception { - Map> map = new HashMap<>(); + Map> map = new HashMap>(); map.put("my-header", Arrays.asList("val")); Request request = Request.create( @@ -68,9 +67,9 @@ public void create() throws Exception { assertThat(requestKey.getMethod(), equalTo(HttpMethod.GET)); assertThat(requestKey.getUrl(), equalTo("a")); - assertThat(requestKey.getHeaders().entrySet(), hasSize(1)); + assertThat(requestKey.getHeaders().size(), is(1)); assertThat( - requestKey.getHeaders().get("my-header"), + requestKey.getHeaders().fetch("my-header"), equalTo((Collection) Arrays.asList("val"))); assertThat(requestKey.getCharset(), equalTo(StandardCharsets.UTF_16)); assertThat(requestKey.getBody(), equalTo("content".getBytes(StandardCharsets.UTF_8))); @@ -120,11 +119,10 @@ public void equalMinimum() { @Test public void equalExtra() { - Map> map = new HashMap<>(); - map.put("my-other-header", Arrays.asList("other value")); + RequestHeaders headers = RequestHeaders.builder().add("my-other-header", "other value").build(); RequestKey requestKey2 = RequestKey.builder(HttpMethod.GET, "a") - .headers(map) + .headers(headers) .charset(StandardCharsets.ISO_8859_1) .build(); @@ -142,11 +140,10 @@ public void equalsExtended() { @Test public void equalsExtendedExtra() { - Map> map = new HashMap<>(); - map.put("my-other-header", Arrays.asList("other value")); + RequestHeaders headers = RequestHeaders.builder().add("my-other-header", "other value").build(); RequestKey requestKey2 = RequestKey.builder(HttpMethod.GET, "a") - .headers(map) + .headers(headers) .charset(StandardCharsets.ISO_8859_1) .build(); @@ -158,7 +155,8 @@ public void equalsExtendedExtra() { public void testToString() throws Exception { assertThat(requestKey.toString(), startsWith("Request [GET a: ")); assertThat( - requestKey.toString(), both(containsString(" with 1 ")).and(containsString(" UTF-16]"))); + requestKey.toString(), + both(containsString(" with my-header=[val] ")).and(containsString(" UTF-16]"))); } @Test