responseExpectations) {
+ return responseExpectations;
+ }
+
+ /**
+ * Getter for the {@link HttpClientPOJOAdapter} that is actually used to make the
+ * HTTP request.
+ *
+ * @return the {@link HttpClientPOJOAdapter}.
+ */
+ public HttpClientPOJOAdapter getHttpClientPOJOAdapter() {
+ return adapter;
+ }
+
+}
\ No newline at end of file
Index: src/main/java/org/apache/hc/client5/http/testframework/HttpServerTestingFramework.java
===================================================================
--- src/main/java/org/apache/hc/client5/http/testframework/HttpServerTestingFramework.java (revision 0)
+++ src/main/java/org/apache/hc/client5/http/testframework/HttpServerTestingFramework.java (revision 0)
@@ -0,0 +1,484 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.hc.client5.http.testframework;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.hc.core5.http.HttpVersion;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.bootstrap.io.HttpServer;
+import org.apache.hc.core5.http.bootstrap.io.ServerBootstrap;
+import org.apache.hc.core5.http.config.SocketConfig;
+
+/**
+ * This testing framework starts an in-process {@link HttpServer} which will use an
+ * {@link HttpServerTestingRequestHandler} to check HTTP requests that are sent
+ * to it. Before the request is sent, the handler is told what request to expect.
+ * If the received request does not match the request expectations, an exception
+ * is thrown.
+ *
+ * The handler is also told what response to return. This testing framework will
+ * then check the response it receives with what it desired. If they do not
+ * match, an exception is thrown.
+ *
+ * This has been designed to work with any HTTP client. So, for instance, Groovy's
+ * HttpBuilder or RESTClient which uses Apache HttpClient can also be tested with this
+ * testing framework. A different {@link HttpServerTestingAdapter} is used with
+ * different HTTP clients. If testing Apache HttpClient5, the {@link HttpClient5TestingAdapter}
+ * is used. Since use of this testing framework with other projects is desired,
+ * the testframework package has been placed outside the test directory. Care has
+ * been taken to make sure no testing dependency such as JUnit or EasyMock is used
+ * in the framework.
+ *
+ * The {@link HttpClient5TestingAdapter} that is used is either passed into the
+ * constructor or set with setAdapter().
+ *
+ * By default, this framework will go through a series of tests that will exercise
+ * all HTTP methods. If the default tests are not desired, then the deleteTests()
+ * method can be called. Then, custom tests can be added with the addTest() methods.
+ * Of course additional tests can be added with the addTest() method without first
+ * calling deleteTests(). In that case, the default tests and the additional tests
+ * will all run.
+ *
+ * Since this framework has been designed to be used with any HTTP client, the test
+ * is specified with POJO's such as Map, List, and primitives. The test is a Map with
+ * two keys - request and response. See {@link HttpClientPOJOAdapter} for details
+ * on the format of the request and response.
+ *
+ * Once any additional tests have been added, the runTests() method is called to
+ * actually do the testing.
+ *
+ * @since 5.0
+ *
+ */
+public class HttpServerTestingFramework {
+ /**
+ * Use the ALL_METHODS list to conveniently cycle through all HTTP methods.
+ */
+ public static final List ALL_METHODS = Arrays.asList("HEAD", "GET", "DELETE", "POST", "PUT", "PATCH");
+
+ /**
+ * If an {@link HttpClient5TestingAdapter} is unable to return a response in
+ * the format this testing framework is needing, then it will need to check the
+ * item in the response (such as body, status, headers, or contentType) itself and set
+ * the returned value of the item as ALREADY_CHECKED.
+ */
+ public static final Object ALREADY_CHECKED = new Object();
+
+ /**
+ * If a test does not specify a path, this one is used.
+ */
+ public static final String DEFAULT_REQUEST_PATH = "a/path";
+
+ /**
+ * If a test does not specify a body, this one is used.
+ */
+ public static final String DEFAULT_REQUEST_BODY = "{\"location\":\"home\"}";
+
+ /**
+ * If a test does not specify a request contentType, this one is used.
+ */
+ public static final String DEFAULT_REQUEST_CONTENT_TYPE = "application/json";
+
+ /**
+ * If a test does not specify query parameters, these are used.
+ */
+ public static final Map DEFAULT_REQUEST_QUERY;
+
+ /**
+ * If a test does not specify a request headers, these are used.
+ */
+ public static final Map DEFAULT_REQUEST_HEADERS;
+
+ /**
+ * If a test does not specify a protocol version, this one is used.
+ */
+ public static final ProtocolVersion DEFAULT_REQUEST_PROTOCOL_VERSION = HttpVersion.HTTP_1_1;
+
+ /**
+ * If a test does not specify an expected response status, this one is used.
+ */
+ public static final int DEFAULT_RESPONSE_STATUS = 200;
+
+ /**
+ * If a test does not specify an expected response body, this one is used.
+ */
+ public static final String DEFAULT_RESPONSE_BODY = "{\"location\":\"work\"}";
+
+ /**
+ * If a test does not specify an expected response contentType, this one is used.
+ */
+ public static final String DEFAULT_RESPONSE_CONTENT_TYPE = "application/json";
+
+ /**
+ * If a test does not specify expected response headers, these are used.
+ */
+ public static final Map DEFAULT_RESPONSE_HEADERS;
+
+ static {
+ final Map request = new HashMap();
+ request.put("p1", "this");
+ request.put("p2", "that");
+ DEFAULT_REQUEST_QUERY = Collections.unmodifiableMap(request);
+
+ Map headers = new HashMap();
+ headers.put("header1", "stuff");
+ headers.put("header2", "more stuff");
+ DEFAULT_REQUEST_HEADERS = Collections.unmodifiableMap(headers);
+
+ headers = new HashMap();
+ headers.put("header3", "header_three");
+ headers.put("header4", "header_four");
+ DEFAULT_RESPONSE_HEADERS = Collections.unmodifiableMap(headers);
+ }
+
+ private HttpServerTestingAdapter adapter;
+ private HttpServerTestingRequestHandler requestHandler = new HttpServerTestingRequestHandler();
+ private List tests = new ArrayList();
+
+ private HttpServer server;
+ private int port;
+
+ public HttpServerTestingFramework() throws HttpServerTestingFrameworkException {
+ this(null);
+ }
+
+ public HttpServerTestingFramework(final HttpServerTestingAdapter adapter) throws HttpServerTestingFrameworkException {
+ this.adapter = adapter;
+
+ /*
+ * By default, a set of tests that will exercise each HTTP method are pre-loaded.
+ */
+ for (String method : ALL_METHODS) {
+ final List statusList = Arrays.asList(200, 201);
+ for (Integer status : statusList) {
+ final Map request = new HashMap();
+ request.put("method", method);
+
+ final Map response = new HashMap();
+ response.put("status", status);
+
+ final Map test = new HashMap();
+ test.put("request", request);
+ test.put("response", response);
+
+ addTest(test);
+ }
+ }
+ }
+
+ /**
+ * This is not likely to be used except during the testing of this class.
+ * It is used to inject a mocked request handler.
+ *
+ * @param requestHandler
+ */
+ public void setRequestHandler(final HttpServerTestingRequestHandler requestHandler) {
+ this.requestHandler = requestHandler;
+ }
+
+ /**
+ * Run the tests that have been previously added. First, an in-process {@link HttpServer} is
+ * started. Then, all the tests are completed by passing each test to the adapter
+ * which will make the HTTP request.
+ *
+ * @throws HttpServerTestingFrameworkException if there is a test failure or unexpected problem.
+ */
+ public void runTests() throws HttpServerTestingFrameworkException {
+ if (adapter == null) {
+ throw new HttpServerTestingFrameworkException("adapter should not be null");
+ }
+
+ startServer();
+
+ try {
+ for (HttpServerTest test : tests) {
+ try {
+ callAdapter(test);
+ } catch (Throwable t) {
+ processThrowable(t, test);
+ }
+ }
+ } finally {
+ stopServer();
+ }
+ }
+
+ private void processThrowable(final Throwable t, final HttpServerTest test) throws HttpServerTestingFrameworkException {
+ HttpServerTestingFrameworkException e;
+ if (t instanceof HttpServerTestingFrameworkException) {
+ e = (HttpServerTestingFrameworkException) t;
+ } else {
+ e = new HttpServerTestingFrameworkException(t);
+ }
+ e.setAdapter(adapter);
+ e.setTest(test);
+ throw e;
+ }
+
+ private void startServer() throws HttpServerTestingFrameworkException {
+ /*
+ * Start an in-process server and handle all HTTP requests
+ * with the requestHandler.
+ */
+ final SocketConfig socketConfig = SocketConfig.custom()
+ .setSoTimeout(15000)
+ .build();
+
+ final ServerBootstrap serverBootstrap = ServerBootstrap.bootstrap()
+ .setSocketConfig(socketConfig)
+ .registerHandler("/*", requestHandler);
+
+ server = serverBootstrap.create();
+ try {
+ server.start();
+ } catch (IOException e) {
+ throw new HttpServerTestingFrameworkException(e);
+ }
+
+ port = server.getLocalPort();
+ }
+
+ private void stopServer() {
+ if (server != null) {
+ server.shutdown(0, TimeUnit.SECONDS);
+ server = null;
+ }
+ }
+
+ private void callAdapter(final HttpServerTest test) throws HttpServerTestingFrameworkException {
+ Map request = test.initRequest();
+
+ /*
+ * If the adapter does not support the particular request, skip the test.
+ */
+ if (! adapter.isRequestSupported(request)) {
+ return;
+ }
+
+ /*
+ * Allow the adapter to modify the request before the request expectations
+ * are given to the requestHandler. Typically, adapters should not have
+ * to modify the request.
+ */
+ request = adapter.modifyRequest(request);
+
+ // Tell the request handler what to expect in the request.
+ requestHandler.setRequestExpectations(request);
+
+ Map responseExpectations = test.initResponseExpectations();
+ /*
+ * Allow the adapter to modify the response expectations before the handler
+ * is told what to return. Typically, adapters should not have to modify
+ * the response expectations.
+ */
+ responseExpectations = adapter.modifyResponseExpectations(request, responseExpectations);
+
+ // Tell the request handler what response to return.
+ requestHandler.setDesiredResponse(responseExpectations);
+
+ /*
+ * Use the adapter to make the HTTP call. Make sure the responseExpectations are not changed
+ * since they have already been sent to the request handler and they will later be used
+ * to check the response.
+ */
+ final String defaultURI = getDefaultURI();
+ final Map response = adapter.execute(
+ defaultURI,
+ request,
+ requestHandler,
+ Collections.unmodifiableMap(responseExpectations));
+ /*
+ * The adapter is welcome to call assertNothingThrown() earlier, but we will
+ * do it here to make sure it is done. If the handler threw any exception
+ * while checking the request it received, it will be re-thrown here.
+ */
+ requestHandler.assertNothingThrown();
+
+ assertResponseMatchesExpectation(request.get("method"), response, responseExpectations);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void assertResponseMatchesExpectation(final Object method, final Map actualResponse,
+ final Map expectedResponse)
+ throws HttpServerTestingFrameworkException {
+ if (actualResponse == null) {
+ throw new HttpServerTestingFrameworkException("response should not be null");
+ }
+ /*
+ * Now check the items in the response unless the adapter says they
+ * already checked something.
+ */
+ if (actualResponse.get("status") != HttpServerTestingFramework.ALREADY_CHECKED) {
+ assertStatusMatchesExpectation(actualResponse.get("status"), expectedResponse.get("status"));
+ }
+ if (! method.equals("HEAD")) {
+ if (actualResponse.get("body") != HttpServerTestingFramework.ALREADY_CHECKED) {
+ assertBodyMatchesExpectation(actualResponse.get("body"), expectedResponse.get("body"));
+ }
+ if (actualResponse.get("contentType") != HttpServerTestingFramework.ALREADY_CHECKED) {
+ assertContentTypeMatchesExpectation(actualResponse.get("contentType"), expectedResponse.get("contentType"));
+ }
+ }
+ if (actualResponse.get("headers") != HttpServerTestingFramework.ALREADY_CHECKED) {
+ assertHeadersMatchExpectation((Map) actualResponse.get("headers"),
+ (Map) expectedResponse.get("headers"));
+ }
+ }
+
+ private void assertStatusMatchesExpectation(final Object actualStatus, final Object expectedStatus)
+ throws HttpServerTestingFrameworkException {
+ if (actualStatus == null) {
+ throw new HttpServerTestingFrameworkException("Returned status is null.");
+ }
+ if ((expectedStatus != null) && (! actualStatus.equals(expectedStatus))) {
+ throw new HttpServerTestingFrameworkException("Expected status not found. expected="
+ + expectedStatus + "; actual=" + actualStatus);
+ }
+ }
+
+ private void assertBodyMatchesExpectation(final Object actualBody, final Object expectedBody)
+ throws HttpServerTestingFrameworkException {
+ if (actualBody == null) {
+ throw new HttpServerTestingFrameworkException("Returned body is null.");
+ }
+ if ((expectedBody != null) && (! actualBody.equals(expectedBody))) {
+ throw new HttpServerTestingFrameworkException("Expected body not found. expected="
+ + expectedBody + "; actual=" + actualBody);
+ }
+ }
+
+ private void assertContentTypeMatchesExpectation(final Object actualContentType, final Object expectedContentType)
+ throws HttpServerTestingFrameworkException {
+ if (expectedContentType != null) {
+ if (actualContentType == null) {
+ throw new HttpServerTestingFrameworkException("Returned contentType is null.");
+ }
+ if (! actualContentType.equals(expectedContentType)) {
+ throw new HttpServerTestingFrameworkException("Expected content type not found. expected="
+ + expectedContentType + "; actual=" + actualContentType);
+ }
+ }
+ }
+
+ private void assertHeadersMatchExpectation(final Map actualHeaders,
+ final Map expectedHeaders)
+ throws HttpServerTestingFrameworkException {
+ if (expectedHeaders == null) {
+ return;
+ }
+ for (Map.Entry expectedHeader : ((Map) expectedHeaders).entrySet()) {
+ final String expectedHeaderName = expectedHeader.getKey();
+ if (! actualHeaders.containsKey(expectedHeaderName)) {
+ throw new HttpServerTestingFrameworkException("Expected header not found: name=" + expectedHeaderName);
+ }
+ if (! actualHeaders.get(expectedHeaderName).equals(expectedHeaders.get(expectedHeaderName))) {
+ throw new HttpServerTestingFrameworkException("Header value not expected: name=" + expectedHeaderName
+ + "; expected=" + expectedHeaders.get(expectedHeaderName)
+ + "; actual=" + actualHeaders.get(expectedHeaderName));
+ }
+ }
+ }
+
+ private String getDefaultURI() {
+ return "http://localhost:" + port + "/";
+ }
+
+ /**
+ * Sets the {@link HttpServerTestingAdapter}.
+ *
+ * @param adapter
+ */
+ public void setAdapter(final HttpServerTestingAdapter adapter) {
+ this.adapter = adapter;
+ }
+
+ /**
+ * Deletes all tests.
+ */
+ public void deleteTests() {
+ tests = new ArrayList();
+ }
+
+ /**
+ * Call to add a test with defaults.
+ *
+ * @throws HttpServerTestingFrameworkException
+ */
+ public void addTest() throws HttpServerTestingFrameworkException {
+ addTest(null);
+ }
+
+ /**
+ * Call to add a test. The test is a map with a "request" and a "response" key.
+ * See {@link HttpClientPOJOAdapter} for details on the format of the request and response.
+ *
+ * @param test Map with a "request" and a "response" key.
+ * @throws HttpServerTestingFrameworkException
+ */
+ @SuppressWarnings("unchecked")
+ public void addTest(final Map test) throws HttpServerTestingFrameworkException {
+ final Map testCopy = (Map) deepcopy(test);
+
+ tests.add(new HttpServerTest(testCopy));
+ }
+
+ /**
+ * Used to make a "deep" copy of an object. This testing framework makes deep copies
+ * of tests that are added as well as requestExpectations Maps and response Maps.
+ *
+ * @param orig a serializable object.
+ * @return a deep copy of the orig object.
+ * @throws HttpServerTestingFrameworkException
+ */
+ public static Object deepcopy(final Object orig) throws HttpServerTestingFrameworkException {
+ try {
+ // this is from http://stackoverflow.com/questions/13155127/deep-copy-map-in-groovy
+ final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ final ObjectOutputStream oos = new ObjectOutputStream(bos);
+ oos.writeObject(orig);
+ oos.flush();
+ final ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());
+ final ObjectInputStream ois = new ObjectInputStream(bin);
+ return ois.readObject();
+ } catch (ClassNotFoundException | IOException e) {
+ throw new HttpServerTestingFrameworkException(e);
+ }
+ }
+}
\ No newline at end of file
Index: src/main/java/org/apache/hc/client5/http/testframework/HttpServerTestingFrameworkException.java
===================================================================
--- src/main/java/org/apache/hc/client5/http/testframework/HttpServerTestingFrameworkException.java (revision 0)
+++ src/main/java/org/apache/hc/client5/http/testframework/HttpServerTestingFrameworkException.java (revision 0)
@@ -0,0 +1,92 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.hc.client5.http.testframework;
+
+import org.apache.hc.core5.annotation.Immutable;
+
+/**
+ * Signals a problem or an assertion failure while using the {@link HttpServerTestingFramework}.
+ *
+ * Optionally, an adapter and a test can be added to the exception. If this is done,
+ * the adapter name and the test information is appended to the exception message to help
+ * determine what test is having a problem.
+ *
+ * @since 5.0
+ */
+@Immutable
+public class HttpServerTestingFrameworkException extends Exception {
+ private HttpServerTestingAdapter adapter;
+
+ private HttpServerTest test;
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1010516169283589675L;
+
+ /**
+ * Creates a WebServerTestingFrameworkException with the specified detail message.
+ */
+ public HttpServerTestingFrameworkException(final String message) {
+ super(message);
+ }
+
+ public HttpServerTestingFrameworkException(final Throwable cause) {
+ super(cause);
+ }
+
+ @Override
+ public String getMessage() {
+ String message = super.getMessage();
+ if (adapter != null) {
+ final HttpClientPOJOAdapter pojoAdapter = adapter.getHttpClientPOJOAdapter();
+ final String httpClient = pojoAdapter == null ? null : pojoAdapter.getHTTPClientName();
+ if (httpClient != null) {
+ if (message == null) {
+ message = "null";
+ }
+ message += "\nHTTP Client=" + httpClient;
+ }
+ }
+ if (test != null) {
+ if (message == null) {
+ message = "null";
+ }
+ message += "\ntest:\n" + test;
+ }
+ return message;
+ }
+
+ public void setAdapter(final HttpServerTestingAdapter adapter) {
+ this.adapter = adapter;
+ }
+
+ public void setTest(final HttpServerTest test) {
+ this.test = test;
+ }
+}
Index: src/main/java/org/apache/hc/client5/http/testframework/HttpServerTestingRequestHandler.java
===================================================================
--- src/main/java/org/apache/hc/client5/http/testframework/HttpServerTestingRequestHandler.java (revision 0)
+++ src/main/java/org/apache/hc/client5/http/testframework/HttpServerTestingRequestHandler.java (revision 0)
@@ -0,0 +1,259 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.hc.client5.http.testframework;
+
+import java.io.IOException;
+import java.net.URI;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.hc.client5.http.utils.URLEncodedUtils;
+import org.apache.hc.core5.http.Header;
+import org.apache.hc.core5.http.HttpEntity;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.NameValuePair;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.entity.ContentType;
+import org.apache.hc.core5.http.entity.EntityUtils;
+import org.apache.hc.core5.http.entity.StringEntity;
+import org.apache.hc.core5.http.io.HttpRequestHandler;
+import org.apache.hc.core5.http.protocol.HttpContext;
+
+/**
+ * This request handler is used with an in-process instance of HttpServer during testing.
+ * The handler is told what to expect in the request. If the request does not match
+ * the expectations, the handler will throw an exception which is then caught and
+ * saved in the "thrown" member. The testing framework will later call assertNothingThrown().
+ * If something was thrown earlier by the handler, an exception will be thrown by the method.
+ *
+ * The handler is also told what response to return.
+ *
+ * See {@link HttpClientPOJOAdapter} for details on the format of the request and response.
+ *
+ * @since 5.0
+ *
+ */
+public class HttpServerTestingRequestHandler implements HttpRequestHandler {
+ protected Throwable thrown;
+ protected Map requestExpectations;
+ protected Map desiredResponse;
+
+ /**
+ * Sets the request expectations.
+ *
+ * @param requestExpectations the expected values of the request.
+ * @throws HttpServerTestingFrameworkException
+ */
+ @SuppressWarnings("unchecked")
+ public void setRequestExpectations(final Map requestExpectations) throws HttpServerTestingFrameworkException {
+ this.requestExpectations = (Map) HttpServerTestingFramework.deepcopy(requestExpectations);
+ }
+
+ /**
+ * Sets the desired response. The handler will return a response that matches this.
+ *
+ * @param desiredResponse the desired response.
+ * @throws HttpServerTestingFrameworkException
+ */
+ @SuppressWarnings("unchecked")
+ public void setDesiredResponse(final Map desiredResponse) throws HttpServerTestingFrameworkException {
+ this.desiredResponse = (Map) HttpServerTestingFramework.deepcopy(desiredResponse);
+ }
+
+ /**
+ * After the handler returns the response, any exception or failed assertion will be
+ * in the member called "thrown". A testing framework can later call this method
+ * which will rethrow the exception that was thrown before.
+ *
+ * @throws HttpServerTestingFrameworkException
+ */
+ public void assertNothingThrown() throws HttpServerTestingFrameworkException {
+ if (thrown != null) {
+ final HttpServerTestingFrameworkException e = (thrown instanceof HttpServerTestingFrameworkException ?
+ (HttpServerTestingFrameworkException) thrown :
+ new HttpServerTestingFrameworkException(thrown));
+ thrown = null;
+ throw e;
+ }
+ }
+
+ /**
+ * Checks the HTTP request against the requestExpectations that it was previously given.
+ * If there is a mismatch, an exception will be saved in the "thrown" member.
+ *
+ * Also, a response will be returned that matches the desiredResponse.
+ */
+ @Override
+ public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context)
+ throws HttpException, IOException {
+
+ try {
+ /*
+ * Check the method against the method in the requestExpectations.
+ */
+ final String actualMethod = request.getRequestLine().getMethod();
+ final String expectedMethod = (String) requestExpectations.get("method");
+ if (! actualMethod.equals(expectedMethod)) {
+ throw new HttpServerTestingFrameworkException("Method not expected. " +
+ " expected=" + expectedMethod + "; actual=" + actualMethod);
+ }
+
+ /*
+ * Set the status to the status that is in the desiredResponse.
+ */
+ final Object desiredStatus = desiredResponse.get("status");
+ if (desiredStatus != null) {
+ response.setStatusCode((int) desiredStatus);
+ }
+
+ /*
+ * Check the query parameters against the parametes in requestExpectations.
+ */
+ @SuppressWarnings("unchecked")
+ final Map expectedQuery = (Map) requestExpectations.get("query");
+ if (expectedQuery != null) {
+ final URI uri = new URI(request.getRequestLine().getUri());
+ final List actualParams = URLEncodedUtils.parse(uri, StandardCharsets.UTF_8);
+ final Map actualParamsMap = new HashMap();
+ for (NameValuePair actualParam : actualParams) {
+ actualParamsMap.put(actualParam.getName(), actualParam.getValue());
+ }
+ for (Map.Entry expectedParam : expectedQuery.entrySet()) {
+ final String key = expectedParam.getKey();
+ if (! actualParamsMap.containsKey(key)) {
+ throw new HttpServerTestingFrameworkException("Expected parameter not found: " + key);
+ }
+ final String actualParamValue = actualParamsMap.get(key);
+ final String expectedParamValue = expectedParam.getValue();
+ if (! actualParamValue.equals(expectedParamValue)) {
+ throw new HttpServerTestingFrameworkException("Expected parameter value not found. " +
+ " Parameter=" + key + "; expected=" + expectedParamValue + "; actual=" + actualParamValue);
+ }
+ }
+ }
+
+ /*
+ * Check the headers against the headers in requestExpectations.
+ */
+ @SuppressWarnings("unchecked")
+ final Map expectedHeaders = (Map) requestExpectations.get("headers");
+ if (expectedHeaders != null) {
+ final Map actualHeadersMap = new HashMap();
+ final Header[] actualHeaders = request.getAllHeaders();
+ for (Header header : actualHeaders) {
+ actualHeadersMap.put(header.getName(), header.getValue());
+ }
+ for (Entry expectedHeader : expectedHeaders.entrySet()) {
+ final String key = expectedHeader.getKey();
+ if (! actualHeadersMap.containsKey(key)) {
+ throw new HttpServerTestingFrameworkException("Expected header not found: " + key);
+ }
+ final String actualHeaderValue = actualHeadersMap.get(key);
+ final String expectedHeaderValue = expectedHeader.getValue();
+ if (! actualHeaderValue.equals(expectedHeaderValue)) {
+ throw new HttpServerTestingFrameworkException("Expected header value not found. " +
+ " Name=" + key + "; expected=" + expectedHeaderValue + "; actual=" + actualHeaderValue);
+ }
+ }
+ }
+
+ /*
+ * Check the body.
+ */
+ final String expectedBody = (String) requestExpectations.get("body");
+ if (expectedBody != null) {
+ final HttpEntity entity = request.getEntity();
+ final String data = EntityUtils.toString(entity);
+ if (! data.equals(expectedBody)) {
+ throw new HttpServerTestingFrameworkException("Expected body not found. " +
+ " Body=" + data + "; expected=" + expectedBody);
+ }
+ }
+
+ /*
+ * Check the contentType of the request.
+ */
+ final String requestContentType = (String) requestExpectations.get("contentType");
+ if (requestContentType != null) {
+ final HttpEntity entity = request.getEntity();
+ final String contentType = entity.getContentType();
+ final String expectedContentType = (String) requestExpectations.get("contentType");
+ if (! contentType.equals(expectedContentType)) {
+ throw new HttpServerTestingFrameworkException("Expected request content type not found. " +
+ " Content Type=" + contentType + "; expected=" + expectedContentType);
+ }
+ }
+
+ /*
+ * Check the protocolVersion.
+ */
+ if (requestExpectations.containsKey("protocolVersion")) {
+ final ProtocolVersion protocolVersion = request.getRequestLine().getProtocolVersion();
+ final ProtocolVersion expectedProtocolVersion = (ProtocolVersion) requestExpectations.get("protocolVersion");
+ if (! protocolVersion.equals(expectedProtocolVersion)) {
+ throw new HttpServerTestingFrameworkException("Expected request protocol version not found. " +
+ " Protocol Version=" + protocolVersion + "; expected=" + expectedProtocolVersion);
+ }
+ }
+
+ /*
+ * Return the body in desiredResponse using the contentType in desiredResponse.
+ */
+ final String desiredBody = (String) desiredResponse.get("body");
+ if (desiredBody != null) {
+ final String desiredContentType = (String) desiredResponse.get("contentType");
+ final StringEntity entity = desiredContentType != null ?
+ new StringEntity(desiredBody, ContentType.parse(desiredContentType)) :
+ new StringEntity(desiredBody);
+ response.setEntity(entity);
+ }
+
+ /*
+ * Return the headers in desiredResponse.
+ */
+ @SuppressWarnings("unchecked")
+ final Map desiredHeaders = (Map) desiredResponse.get("headers");
+ if (desiredHeaders != null) {
+ for (Entry entry : desiredHeaders.entrySet()) {
+ response.setHeader(entry.getKey(), entry.getValue());
+ }
+ }
+
+ } catch (Throwable t) {
+ /*
+ * Save the throwable to be later retrieved by a call to assertNothingThrown().
+ */
+ thrown = t;
+ }
+ }
+}
Index: src/test/java/org/apache/hc/client5/http/testframework/TestHttpClient5Adapter.java
===================================================================
--- src/test/java/org/apache/hc/client5/http/testframework/TestHttpClient5Adapter.java (revision 0)
+++ src/test/java/org/apache/hc/client5/http/testframework/TestHttpClient5Adapter.java (revision 0)
@@ -0,0 +1,261 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.hc.client5.http.testframework;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.apache.hc.client5.http.localserver.LocalServerTestBase;
+import org.apache.hc.core5.http.HttpException;
+import org.apache.hc.core5.http.HttpHost;
+import org.apache.hc.core5.http.HttpRequest;
+import org.apache.hc.core5.http.HttpResponse;
+import org.apache.hc.core5.http.protocol.HttpContext;
+import org.junit.Assert;
+
+public class TestHttpClient5Adapter extends LocalServerTestBase {
+ private static final String ECHO_PATH = "echo/something";
+ private static final String CUSTOM_PATH = "custom/something";
+
+ @Test
+ public void nullDefaultURI() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final String defaultURI = null;
+ final Map request = new HashMap();
+ final HttpServerTestingRequestHandler requestHandler = Mockito.mock(HttpServerTestingRequestHandler.class);
+ final Map responseExpectations = new HashMap();
+
+ try {
+ adapter.execute(defaultURI, request, requestHandler, responseExpectations);
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void nullRequest() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final String defaultURI = "";
+ final Map request = null;
+ final HttpServerTestingRequestHandler requestHandler = Mockito.mock(HttpServerTestingRequestHandler.class);
+ final Map responseExpectations = new HashMap();
+
+ try {
+ adapter.execute(defaultURI, request, requestHandler, responseExpectations);
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void nullRequestHandler() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final String defaultURI = "";
+ final Map request = new HashMap();
+ final HttpServerTestingRequestHandler requestHandler = null;
+ final Map responseExpectations = new HashMap();
+
+ try {
+ adapter.execute(defaultURI, request, requestHandler, responseExpectations);
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void nullResponseExpectations() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final String defaultURI = "";
+ final Map request = new HashMap();
+ final HttpServerTestingRequestHandler requestHandler = Mockito.mock(HttpServerTestingRequestHandler.class);
+ final Map responseExpectations = null;
+
+ try {
+ adapter.execute(defaultURI, request, requestHandler, responseExpectations);
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void noPath() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final String defaultURI = "";
+ final Map request = new HashMap();
+ final HttpServerTestingRequestHandler requestHandler = Mockito.mock(HttpServerTestingRequestHandler.class);
+ final Map responseExpectations = new HashMap();
+
+ try {
+ adapter.execute(defaultURI, request, requestHandler, responseExpectations);
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void noMethod() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final String defaultURI = "";
+
+ final Map request = new HashMap();
+ request.put("path", ECHO_PATH);
+
+ final HttpServerTestingRequestHandler requestHandler = Mockito.mock(HttpServerTestingRequestHandler.class);
+ final Map responseExpectations = new HashMap();
+
+ try {
+ adapter.execute(defaultURI, request, requestHandler, responseExpectations);
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void invalidMethod() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final String defaultURI = "";
+
+ final Map request = new HashMap();
+ request.put("path", ECHO_PATH);
+ request.put("method", "JUNK");
+
+ final HttpServerTestingRequestHandler requestHandler = Mockito.mock(HttpServerTestingRequestHandler.class);
+ final Map responseExpectations = new HashMap();
+
+ try {
+ adapter.execute(defaultURI, request, requestHandler, responseExpectations);
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void withLiveServerEcho() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final HttpHost target = start();
+
+ final String defaultURI = target.toString();
+ final Map request = new HashMap();
+ request.put("path", ECHO_PATH);
+ request.put("method", "POST");
+ final String body = "mybody";
+ request.put("body", body);
+
+ final HttpServerTestingRequestHandler requestHandler = Mockito.mock(HttpServerTestingRequestHandler.class);
+ final Map responseExpectations = new HashMap();
+
+ final Map response = adapter.execute(defaultURI, request, requestHandler, responseExpectations);
+
+ Assert.assertNotNull("response should not be null", response);
+ Assert.assertEquals("status unexpected", 200, response.get("status"));
+
+ @SuppressWarnings("unchecked")
+ final Map headers = (Map) response.get("headers");
+ Assert.assertNotNull("headers should be in the response", headers);
+ Assert.assertFalse(headers.isEmpty());
+
+ final String returnedBody = (String) response.get("body");
+ Assert.assertNotNull("body should be in the response", returnedBody);
+ Assert.assertEquals("Body should be echoed", body, returnedBody);
+
+ server.shutdown(0, TimeUnit.SECONDS); // 0 seconds to speed up the test.
+ server = null;
+ }
+
+ @Test
+ public void withLiveServerCustomRequestHandler() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final HttpServerTestingRequestHandler requestHandler = new HttpServerTestingRequestHandler() {
+ @Override
+ public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context)
+ throws HttpException, IOException {
+ try {
+ Assert.assertEquals("method not expected", "junk", request.getRequestLine().getMethod());
+ } catch (Throwable t) {
+ thrown = t;
+ }
+ }
+ };
+ serverBootstrap.registerHandler("/custom/*", requestHandler);
+
+ final HttpHost target = start();
+ final String defaultURI = target.toString();
+ final Map responseExpectations = new HashMap();
+
+ final Map request = new HashMap();
+ request.put("path", CUSTOM_PATH);
+
+ for (String method : HttpServerTestingFramework.ALL_METHODS) {
+ request.put("method", method);
+
+ adapter.execute(defaultURI, request, requestHandler, responseExpectations);
+ }
+ server.shutdown(0, TimeUnit.SECONDS); // 0 seconds to speed up the test.
+ server = null;
+ }
+
+ @Test
+ public void modifyRequest() {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final Map request = new HashMap();
+ final Map returnedRequest = adapter.modifyRequest(request);
+
+ Assert.assertSame("Same request was not returned as expected.", request, returnedRequest);
+ }
+
+ @Test
+ public void modifyResponseExpectations() {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final Map responseExpectations = new HashMap();
+ final Map returnedResponseExpectations = adapter.modifyResponseExpectations(null, responseExpectations);
+
+ Assert.assertSame("Same response expectations were not returned as expected.", responseExpectations, returnedResponseExpectations);
+ }
+}
Index: src/test/java/org/apache/hc/client5/http/testframework/TestHttpClientPOJOAdapter.java
===================================================================
--- src/test/java/org/apache/hc/client5/http/testframework/TestHttpClientPOJOAdapter.java (revision 0)
+++ src/test/java/org/apache/hc/client5/http/testframework/TestHttpClientPOJOAdapter.java (revision 0)
@@ -0,0 +1,82 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+package org.apache.hc.client5.http.testframework;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestHttpClientPOJOAdapter {
+ @Test
+ public void modifyRequest() throws Exception {
+ final HttpClientPOJOAdapter adapter = new HttpClient5Adapter();
+ final Map request = new HashMap();
+ final Map request2 = adapter.modifyRequest(request);
+
+ Assert.assertSame("request should have been returned", request, request2);
+ }
+
+ @Test
+ public void checkRequestSupport() throws Exception {
+ final HttpClientPOJOAdapter adapter = new HttpClient5Adapter();
+ final String reason = adapter.checkRequestSupport(null);
+
+ Assert.assertNull("reason should be null", reason);
+
+ adapter.assertRequestSupported(null);
+ }
+
+ @Test
+ public void checkRequestSupportThrows() throws Exception {
+ final HttpClientPOJOAdapter adapter = new HttpClientPOJOAdapter() {
+
+ @Override
+ public Map execute(final String defaultURI, final Map request) throws Exception {
+ return null;
+ }
+
+ @Override
+ public String checkRequestSupport(final java.util.Map request) {
+ return "A reason this request is not supported.";
+ }
+
+ @Override
+ public String getHTTPClientName() {
+ return null;
+ };
+ };
+
+ try {
+ adapter.assertRequestSupported(null);
+ Assert.fail("A WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+}
Index: src/test/java/org/apache/hc/client5/http/testframework/TestHttpServerTest.java
===================================================================
--- src/test/java/org/apache/hc/client5/http/testframework/TestHttpServerTest.java (revision 0)
+++ src/test/java/org/apache/hc/client5/http/testframework/TestHttpServerTest.java (revision 0)
@@ -0,0 +1,106 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.hc.client5.http.testframework;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import org.junit.Assert;
+
+public class TestHttpServerTest {
+ @Test
+ public void defaults() throws Exception {
+ final HttpServerTest test = new HttpServerTest();
+ final Map request = test.initRequest();
+
+ Assert.assertNotNull("request should not be null", request);
+ Assert.assertEquals("Default method should be GET", "GET", request.get("method"));
+
+ Assert.assertEquals("Default request body expected.",
+ HttpServerTestingFramework.DEFAULT_REQUEST_BODY,
+ request.get("body"));
+
+ Assert.assertEquals("Default request content type expected.",
+ HttpServerTestingFramework.DEFAULT_REQUEST_CONTENT_TYPE,
+ request.get("contentType"));
+
+ Assert.assertEquals("Default request query parameters expected.",
+ HttpServerTestingFramework.DEFAULT_REQUEST_QUERY,
+ request.get("query"));
+
+ Assert.assertEquals("Default request headers expected.",
+ HttpServerTestingFramework.DEFAULT_REQUEST_HEADERS,
+ request.get("headers"));
+
+ Assert.assertEquals("Default protocol version expected.",
+ HttpServerTestingFramework.DEFAULT_REQUEST_PROTOCOL_VERSION,
+ request.get("protocolVersion"));
+
+ final Map responseExpectations = test.initResponseExpectations();
+ Assert.assertNotNull("responseExpectations should not be null", responseExpectations);
+ Assert.assertEquals("Default status expected.", HttpServerTestingFramework.DEFAULT_RESPONSE_STATUS,
+ responseExpectations.get("status"));
+
+ Assert.assertEquals("Default body expected.", HttpServerTestingFramework.DEFAULT_RESPONSE_BODY,
+ responseExpectations.get("body"));
+
+ Assert.assertEquals("Default response content type expected.", HttpServerTestingFramework.DEFAULT_RESPONSE_CONTENT_TYPE,
+ responseExpectations.get("contentType"));
+
+ Assert.assertEquals("Default headers expected.", HttpServerTestingFramework.DEFAULT_RESPONSE_HEADERS,
+ responseExpectations.get("headers"));
+ }
+
+ @Test
+ public void changeStatus() throws Exception {
+ final Map testMap = new HashMap();
+ final Map response = new HashMap();
+ testMap.put("response", response);
+ response.put("status", 201);
+
+ final HttpServerTest test = new HttpServerTest(testMap);
+ final Map responseExpectations = test.initResponseExpectations();
+
+ Assert.assertEquals("Status unexpected.", 201, responseExpectations.get("status"));
+ }
+
+ @Test
+ public void changeMethod() throws Exception {
+ final Map testMap = new HashMap();
+ final Map request = new HashMap();
+ testMap.put("request", request);
+ request.put("method", "POST");
+
+ final HttpServerTest test = new HttpServerTest(testMap);
+ final Map requestExpectations = test.initRequest();
+
+ Assert.assertEquals("Method unexpected.", "POST", requestExpectations.get("method"));
+ }
+}
Index: src/test/java/org/apache/hc/client5/http/testframework/TestHttpServerTestingAdapter.java
===================================================================
--- src/test/java/org/apache/hc/client5/http/testframework/TestHttpServerTestingAdapter.java (revision 0)
+++ src/test/java/org/apache/hc/client5/http/testframework/TestHttpServerTestingAdapter.java (revision 0)
@@ -0,0 +1,53 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+package org.apache.hc.client5.http.testframework;
+
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestHttpServerTestingAdapter {
+
+ @Test
+ public void getHttpClientPOJOAdapter() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final HttpClientPOJOAdapter pojoAdapter = adapter.getHttpClientPOJOAdapter();
+
+ Assert.assertNotNull("pojoAdapter should not be null", pojoAdapter);
+ }
+
+ @Test
+ public void isRequestSupported() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final Map request = null;
+ Assert.assertTrue("isRequestSupported should return true", adapter.isRequestSupported(request));
+
+ }
+}
Index: src/test/java/org/apache/hc/client5/http/testframework/TestHttpServerTestingFramework.java
===================================================================
--- src/test/java/org/apache/hc/client5/http/testframework/TestHttpServerTestingFramework.java (revision 0)
+++ src/test/java/org/apache/hc/client5/http/testframework/TestHttpServerTestingFramework.java (revision 0)
@@ -0,0 +1,1151 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.hc.client5.http.testframework;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.hc.core5.http.HttpVersion;
+import org.apache.hc.core5.http.ProtocolVersion;
+import org.apache.hc.core5.http.entity.ContentType;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class TestHttpServerTestingFramework {
+
+ @Test
+ public void ensureDefaultMapsUnmodifiable() throws Exception {
+ assertUnmodifiable(HttpServerTestingFramework.DEFAULT_REQUEST_QUERY);
+ assertUnmodifiable(HttpServerTestingFramework.DEFAULT_RESPONSE_HEADERS);
+ }
+
+ private void assertUnmodifiable(final Map map) {
+ final String aKey = (String) map.keySet().toArray()[0];
+ try {
+ map.remove(aKey);
+ Assert.fail("UnsupportedOperationException should have been thrown.");
+ } catch (UnsupportedOperationException e) {
+ // expected
+ }
+ }
+
+ private HttpServerTestingFramework newWebServerTestingFramework(final HttpServerTestingAdapter adapter)
+ throws HttpServerTestingFrameworkException {
+ final HttpServerTestingFramework framework = new HttpServerTestingFramework(adapter);
+ // get rid of the default tests.
+ framework.deleteTests();
+
+ return framework;
+ }
+
+ private HttpServerTestingFramework newWebServerTestingFramework() throws HttpServerTestingFrameworkException {
+ return newWebServerTestingFramework(null); // null adapter
+ }
+
+ @Test
+ public void runTestsWithoutSettingAdapterThrows() throws Exception {
+ final HttpServerTestingFramework framework = newWebServerTestingFramework();
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void nullAdapterThrows() throws Exception {
+ final HttpServerTestingAdapter adapter = null;
+
+ final HttpServerTestingFramework framework = newWebServerTestingFramework(adapter);
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void nullSetAdapterThrows() throws Exception {
+ final HttpServerTestingAdapter adapter = null;
+
+ final HttpServerTestingFramework framework = newWebServerTestingFramework(adapter);
+ framework.setAdapter(adapter);
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Test
+ public void goodAdapterWithConstructor() throws Exception {
+ final HttpServerTestingAdapter adapter = Mockito.mock(HttpServerTestingAdapter.class);
+
+ // Have isRequestSupported() return false so no test will run.
+ Mockito.when(adapter.isRequestSupported(Mockito.anyMap()))
+ .thenReturn(false);
+
+ final HttpServerTestingFramework framework = newWebServerTestingFramework(adapter);
+
+ framework.runTests();
+
+ // since there are no tests, callMethod should not be called.
+ verifyCallMethodNeverCalled(adapter);
+ }
+
+ @SuppressWarnings("unchecked")
+ private void verifyCallMethodNeverCalled(final HttpServerTestingAdapter adapter) throws Exception {
+ Mockito.verify(adapter, Mockito.never()).execute(Mockito.anyString(), Mockito.anyMap(),
+ Mockito.any(HttpServerTestingRequestHandler.class), Mockito.anyMap());
+ }
+
+ private HttpServerTestingFramework newFrameworkAndSetAdapter(final HttpServerTestingAdapter adapter)
+ throws HttpServerTestingFrameworkException {
+ final HttpServerTestingFramework framework = new HttpServerTestingFramework();
+ framework.setAdapter(adapter);
+
+ // get rid of the default tests.
+ framework.deleteTests();
+
+ return framework;
+ }
+
+ @Test
+ public void goodAdapterWithSetter() throws Exception {
+ final HttpServerTestingAdapter adapter = Mockito.mock(HttpServerTestingAdapter.class);
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.runTests();
+
+ // since there are no tests, callMethod should not be called.
+ verifyCallMethodNeverCalled(adapter);
+ }
+
+ @Test
+ public void addTest() throws Exception {
+ final HttpServerTestingRequestHandler mockRequestHandler = Mockito.mock(HttpServerTestingRequestHandler.class);
+
+ HttpServerTestingAdapter adapter = new HttpServerTestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) throws HttpServerTestingFrameworkException {
+ Assert.assertThat(defaultURI, matchesDefaultURI());
+
+ Assert.assertNotNull("request should not be null", request);
+
+ // The request should be equal to the default request.
+ final Map defaultRequest = new HttpServerTest().initRequest();
+ Assert.assertEquals("The request does not match the default", defaultRequest, request);
+
+ Assert.assertSame("The request handler should have been passed to the adapter",
+ mockRequestHandler, requestHandler);
+
+ // The responseExpectations should be equal to the default.
+ final Map defaultResponseExpectations = new HttpServerTest().initResponseExpectations();
+ Assert.assertEquals("The responseExpectations do not match the defaults",
+ defaultResponseExpectations, responseExpectations);
+
+ final Map response = new HashMap();
+ response.put("status", responseExpectations.get("status"));
+ response.put("body", responseExpectations.get("body"));
+ response.put("contentType", responseExpectations.get("contentType"));
+ response.put("headers", responseExpectations.get("headers"));
+ return response;
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+ framework.setRequestHandler(mockRequestHandler);
+
+ framework.addTest();
+
+ framework.runTests();
+
+ // assertNothingThrown() should have been called.
+ Mockito.verify(mockRequestHandler).assertNothingThrown();
+ }
+
+ private Matcher matchesDefaultURI() {
+ final Matcher matcher = new BaseMatcher() {
+ private final String regex = "http://localhost:\\d+/";
+
+ @Override
+ public boolean matches(final Object o) {
+ return ((String) o).matches(regex);
+ }
+
+ @Override
+ public void describeTo(final Description description) {
+ description.appendText("matches regex=" + regex);
+ }
+ };
+
+ return matcher;
+ }
+
+ @Test
+ public void statusCheck() throws Exception {
+ HttpServerTestingAdapter adapter = new HttpServerTestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) {
+
+ Assert.assertEquals(200, responseExpectations.get("status"));
+
+ // return a different status than expected.
+ final Map response = new HashMap();
+ response.put("status", 201);
+ return response;
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.addTest();
+
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ private Map alreadyCheckedResponse() {
+ // return an indication that the response has already been checked.
+ final Map response = new HashMap();
+ response.put("status", HttpServerTestingFramework.ALREADY_CHECKED);
+ response.put("body", HttpServerTestingFramework.ALREADY_CHECKED);
+ response.put("contentType", HttpServerTestingFramework.ALREADY_CHECKED);
+ response.put("headers", HttpServerTestingFramework.ALREADY_CHECKED);
+ return response;
+ }
+
+ @Test
+ public void responseAlreadyChecked() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpServerTestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) {
+
+ return alreadyCheckedResponse();
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.addTest();
+
+ framework.runTests();
+ }
+
+ @Test
+ public void bodyCheck() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpServerTestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) {
+
+ Assert.assertEquals(HttpServerTestingFramework.DEFAULT_RESPONSE_BODY, responseExpectations.get("body"));
+
+ final Map response = new HashMap();
+ response.put("status", HttpServerTestingFramework.ALREADY_CHECKED);
+
+ // return a different body than expected.
+ response.put("body", HttpServerTestingFramework.DEFAULT_RESPONSE_BODY + "junk");
+ return response;
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.addTest();
+
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void responseContentTypeCheck() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpServerTestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) {
+
+ Assert.assertEquals(HttpServerTestingFramework.DEFAULT_RESPONSE_CONTENT_TYPE, responseExpectations.get("contentType"));
+
+ final Map response = new HashMap();
+ response.put("status", HttpServerTestingFramework.ALREADY_CHECKED);
+ response.put("headers", HttpServerTestingFramework.ALREADY_CHECKED);
+
+ // return the expected body
+ response.put("body", HttpServerTestingFramework.DEFAULT_RESPONSE_BODY);
+ // return a different content type than expected.
+ response.put("contentType", ContentType.DEFAULT_TEXT);
+ return response;
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.addTest();
+
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void deepcopy() throws Exception {
+ // save a copy of the headers to make sure they haven't changed at the end of this test.
+ @SuppressWarnings("unchecked")
+ final Map headersCopy = (Map) HttpServerTestingFramework.deepcopy(HttpServerTestingFramework.DEFAULT_RESPONSE_HEADERS);
+ Assert.assertEquals(HttpServerTestingFramework.DEFAULT_RESPONSE_HEADERS, headersCopy);
+
+ final Map deepMap = new HashMap();
+ deepMap.put("headers", HttpServerTestingFramework.DEFAULT_RESPONSE_HEADERS);
+
+ @SuppressWarnings("unchecked")
+ final Map deepMapCopy = (Map) HttpServerTestingFramework.deepcopy(deepMap);
+ Assert.assertEquals(deepMap, deepMapCopy);
+
+ @SuppressWarnings("unchecked")
+ final Map headersMap = (Map) deepMapCopy.get("headers");
+ Assert.assertEquals(headersCopy, headersMap);
+
+ // now make sure the default headers have not changed for some unexpected reason.
+ Assert.assertEquals(HttpServerTestingFramework.DEFAULT_RESPONSE_HEADERS, headersCopy);
+ }
+
+ @Test
+ public void removedHeaderCheck() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpServerTestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) {
+
+ Assert.assertEquals(HttpServerTestingFramework.DEFAULT_RESPONSE_HEADERS, responseExpectations.get("headers"));
+
+ @SuppressWarnings("unchecked")
+ final Map headersCopy = (Map) deepcopy(responseExpectations.get("headers"));
+
+ // remove a header to force an error
+ final String headerName = (String) headersCopy.keySet().toArray()[0];
+ headersCopy.remove(headerName);
+
+ final Map response = new HashMap();
+ response.put("status", HttpServerTestingFramework.ALREADY_CHECKED);
+ response.put("body", HttpServerTestingFramework.ALREADY_CHECKED);
+
+ // return different headers than expected.
+ response.put("headers", headersCopy);
+ return response;
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.addTest();
+
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void changedHeaderCheck() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpServerTestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) {
+
+ Assert.assertEquals(HttpServerTestingFramework.DEFAULT_RESPONSE_HEADERS, responseExpectations.get("headers"));
+
+ @SuppressWarnings("unchecked")
+ final Map headersCopy = (Map) deepcopy(responseExpectations.get("headers"));
+
+ // change a header to force an error
+ final String headerName = (String) headersCopy.keySet().toArray()[0];
+ headersCopy.put(headerName, headersCopy.get(headerName) + "junk");
+
+ final Map response = new HashMap();
+ response.put("status", HttpServerTestingFramework.ALREADY_CHECKED);
+ response.put("body", HttpServerTestingFramework.ALREADY_CHECKED);
+
+ // return different headers than expected.
+ response.put("headers", headersCopy);
+ return response;
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.addTest();
+
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ private Object deepcopy(final Object obj) {
+ try {
+ return HttpServerTestingFramework.deepcopy(obj);
+ } catch (Exception e) {
+ Assert.fail("deepcopy failed: " + e.getMessage());
+ return null;
+ }
+ }
+
+ @Test
+ public void requestMethodUnexpected() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) throws HttpServerTestingFrameworkException {
+ // change the request from what is expected.
+ Assert.assertTrue(request.get("method").equals("GET"));
+ request.put("method", "POST");
+ return super.execute(defaultURI, request, requestHandler, responseExpectations);
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ final Map test = new HashMap();
+ final Map request = new HashMap();
+ test.put("request", request);
+ request.put("name", "MyName");
+
+ framework.addTest(test);
+
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+
+ // make sure the HTTP Client name is in the message.
+ final String message = e.getMessage();
+ final String httpClientName = adapter.getHttpClientPOJOAdapter().getHTTPClientName();
+ Assert.assertTrue(
+ "Message should contain httpClientName of " + httpClientName + "; message=" + message,
+ message.contains(httpClientName));
+
+ Assert.assertTrue(
+ "Message should contain the test. message=" + message,
+ message.contains("MyName"));
+ }
+ }
+
+ @Test
+ public void status201() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter();
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ final Map test = new HashMap();
+ final Map response = new HashMap();
+ test.put("response", response);
+ response.put("status", 201);
+
+ framework.addTest(test);
+
+ framework.runTests();
+ }
+
+ @Test
+ public void deepcopyOfTest() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpServerTestingAdapter() {
+
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations)
+ throws HttpServerTestingFrameworkException {
+ Assert.assertEquals(201, responseExpectations.get("status"));
+ return alreadyCheckedResponse();
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ final Map test = new HashMap();
+ final Map response = new HashMap();
+ test.put("response", response);
+ response.put("status", 201);
+
+ framework.addTest(test);
+
+ // Make sure the framework makes a copy of the test for itself.
+ // This put should be ignored by the framework.
+ response.put("status", 300);
+
+ framework.runTests();
+ }
+
+ @Test
+ public void removeParameter() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) throws HttpServerTestingFrameworkException {
+ // change the request from what is expected.
+ @SuppressWarnings("unchecked")
+ final Map query = (Map) request.get("query");
+ Assert.assertTrue(query.containsKey("p1"));
+ query.remove("p1");
+ return super.execute(defaultURI, request, requestHandler, responseExpectations);
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.addTest();
+
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void changeParameter() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) throws HttpServerTestingFrameworkException {
+ // change the request from what is expected.
+ @SuppressWarnings("unchecked")
+ final Map query = (Map) request.get("query");
+ Assert.assertTrue(query.containsKey("p1"));
+ query.put("p1", query.get("p1") + "junk");
+ return super.execute(defaultURI, request, requestHandler, responseExpectations);
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.addTest();
+
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void removeHeader() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map request,
+ final HttpServerTestingRequestHandler requestHandler,
+ final Map responseExpectations) throws HttpServerTestingFrameworkException {
+ // change the request from what is expected.
+ @SuppressWarnings("unchecked")
+ final Map headers = (Map) request.get("headers");
+ Assert.assertTrue(headers.containsKey("header1"));
+ headers.remove("header1");
+ return super.execute(defaultURI, request, requestHandler, responseExpectations);
+ }
+ };
+
+ final HttpServerTestingFramework framework = newFrameworkAndSetAdapter(adapter);
+
+ framework.addTest();
+
+ try {
+ framework.runTests();
+ Assert.fail("WebServerTestingFrameworkException should have been thrown");
+ } catch (HttpServerTestingFrameworkException e) {
+ // expected
+ }
+ }
+
+ @Test
+ public void changeHeader() throws Exception {
+ final HttpServerTestingAdapter adapter = new HttpClient5TestingAdapter() {
+ @Override
+ public Map execute(
+ final String defaultURI,
+ final Map