You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2019/03/10 15:52:31 UTC

[juneau] 06/09: Improvements to RestMock APIs.

This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git

commit 211e266234a734e2bacf4f9125e3b85f2dcf7d57
Author: JamesBognar <ja...@apache.org>
AuthorDate: Thu Mar 7 13:36:10 2019 -0500

    Improvements to RestMock APIs.
---
 .../org/apache/juneau/http/HttpMethodName.java     |   3 +
 .../java/org/apache/juneau/marshall/Marshall.java  |  18 +
 .../juneau/pojotools/TimeMatcherFactory.java       |   3 -
 .../apache/juneau/utils/MockHttpConnection.java    |   5 +-
 juneau-doc/docs/ReleaseNotes/8.0.1.html            |   5 +
 juneau-doc/src/main/javadoc/overview.html          |   8 +
 .../org/apache/juneau/rest/test/MockRestTest.java  |   4 +-
 .../rest/test/client/CallbackStringsTest.java      |   2 +-
 .../juneau/rest/test/client/ClientFuturesTest.java |   2 +-
 .../juneau/rest/test/client/FormDataTest.java      |   4 +-
 .../rest/test/client/InterfaceProxyTest.java       |   2 +-
 .../rest/test/client/RequestBeanProxyTest.java     |   8 +-
 juneau-rest/juneau-rest-client/pom.xml             |   1 -
 .../org/apache/juneau/rest/client/RestClient.java  |  69 +++-
 .../juneau/rest/client/RestClientBuilder.java      |  19 +
 .../rest/client/mock/MockHttpClientConnection.java |   4 +-
 .../rest/client/mock/MockRemoteResource.java       | 404 ++++++++++++++++++++
 .../rest/client/remote/BodyAnnotationTest.java     |  13 +-
 .../rest/client/remote/EndToEndInterfaceTest.java  |  24 +-
 .../rest/client/remote/FormDataAnnotationTest.java |  32 +-
 .../rest/client/remote/HeaderAnnotationTest.java   |  32 +-
 .../rest/client/remote/PathAnnotationTest.java     |  26 +-
 .../rest/client/remote/QueryAnnotationTest.java    |  32 +-
 .../client/remote/RemoteMethodAnnotationTest.java  |  20 +-
 .../remote/RemoteResourceAnnotationTest.java       |  16 +-
 .../rest/client/remote/RequestAnnotationTest.java  |  19 +-
 .../rest/client/remote/ResponseAnnotationTest.java |   6 +-
 .../java/org/apache/juneau/rest/RestContext.java   |   2 +-
 .../java/org/apache/juneau/rest/mock/MockRest.java | 425 +++++++++++++++++++--
 .../juneau/rest/mock/MockServletRequest.java       | 102 ++++-
 .../org/apache/juneau/rest/util/RestUtils.java     |  27 ++
 .../jueau/rest/helper/ReaderResourceTest.java      |   2 +-
 .../jueau/rest/helper/StreamResourceTest.java      |   2 +-
 .../juneau/rest/BasicRestInfoProviderTest.java     |   2 +-
 .../juneau/rest/BeanContextPropertiesTest.java     |   2 +-
 .../test/java/org/apache/juneau/rest/NlsTest.java  |   6 +-
 .../java/org/apache/juneau/rest/PathsTest.java     |   8 +-
 .../org/apache/juneau/rest/RestParamsTest.java     |   2 +-
 .../org/apache/juneau/rest/StatusCodesTest.java    |   8 +-
 .../apache/juneau/rest/ThreadLocalObjectsTest.java |   4 +-
 .../juneau/rest/annotation/HtmlDocAsideTest.java   |   4 +-
 .../juneau/rest/annotation/HtmlDocFooterTest.java  |   4 +-
 .../juneau/rest/annotation/HtmlDocHeaderTest.java  |   4 +-
 .../juneau/rest/annotation/HtmlDocNavTest.java     |   4 +-
 .../rest/annotation/HtmlDocNavlinksTest.java       |   4 +-
 .../juneau/rest/annotation/HtmlDocScriptTest.java  |   4 +-
 .../juneau/rest/annotation/HtmlDocStyleTest.java   |   4 +-
 .../annotation/ResponseHeaderAnnotationTest.java   |   2 +-
 .../annotation/ResponseStatusAnnotationTest.java   |   2 +-
 .../juneau/rest/annotation/RestMethodBpiTest.java  |  14 +-
 .../rest/annotation/RestMethodGuardsTest.java      |   2 +-
 .../rest/annotation/RestMethodMatchersTest.java    |   2 +-
 .../juneau/rest/annotation/RestMethodPathTest.java |   2 +-
 .../rest/annotation/RestResourceMessagesTest.java  |   4 +-
 .../rest/annotation/RestResourcePathTest.java      |   2 +-
 .../annotation/RestResourcePropertiesTest.java     |   2 +-
 .../annotation/RestResourceSerializersTest.java    |   2 +-
 .../annotation/RestResourceStaticFilesTest.java    |   4 +-
 .../annotation2/AnnotationInheritanceTest.java     |   2 +-
 .../rest/annotation2/BodyAnnotationTest.java       |  16 +-
 .../rest/annotation2/FormDataAnnotationTest.java   |   6 +-
 .../annotation2/HasFormDataAnnotationTest.java     |   2 +-
 .../rest/annotation2/HasQueryAnnotationTest.java   |   2 +-
 .../rest/annotation2/PathAnnotationTest.java       |  10 +-
 .../annotation2/PathRemainderAnnotationTest.java   |   2 +-
 .../rest/annotation2/QueryAnnotationTest.java      |   8 +-
 .../rest/annotation2/ResponseAnnotationTest.java   |  14 +-
 .../juneau/rest/annotation2/RestHookTest.java      |  16 +-
 .../rest/annotation2/RestMethodInheritTest.java    |   8 +-
 .../rest/annotation2/RestResourceParsersTest.java  |   2 +-
 .../annotation2/RestResourcePojoSwapsTest.java     |   2 +-
 .../apache/juneau/rest/exception/BasicTest.java    |  10 +-
 .../juneau/rest/headers/AcceptCharsetTest.java     |   4 +-
 .../juneau/rest/headers/AcceptEncodingTest.java    |   6 +-
 .../org/apache/juneau/rest/headers/AcceptTest.java |  12 +-
 .../juneau/rest/headers/ClientVersionTest.java     |   4 +-
 .../juneau/rest/headers/ContentEncodingTest.java   |   5 +-
 .../juneau/rest/headers/ContentTypeTest.java       |  10 +-
 .../apache/juneau/rest/headers/HeadersTest.java    |  18 +-
 .../org/apache/juneau/rest/response/BasicTest.java |   8 +-
 .../apache/juneau/rest/testutils/TestUtils.java    |   1 +
 .../org/apache/juneau/rest/util/RestUtilsTest.java |  17 +
 82 files changed, 1275 insertions(+), 349 deletions(-)

diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpMethodName.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpMethodName.java
index 3209764..7183d62 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpMethodName.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/http/HttpMethodName.java
@@ -46,6 +46,9 @@ public final class HttpMethodName {
 	/** {@doc RFC2616.section9#sec9.9 CONNECT} */
 	public static final String CONNECT = "CONNECT";
 
+	/** {@doc https://tools.ietf.org/html/rfc5789 PATCH} */
+	public static final String PATCH = "PATCH";
+
 	/** Special case for a REST method that implements a REST-RPC interface. */
 	public static final String RRPC = "RRPC";
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/Marshall.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/Marshall.java
index bec1206..1209ed7 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/Marshall.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/Marshall.java
@@ -64,6 +64,24 @@ public abstract class Marshall {
 	}
 
 	/**
+	 * Returns the serializer associated with this marshall.
+	 *
+	 * @return The serializer associated with this marshall.
+	 */
+	public Serializer getSerializer() {
+		return s;
+	}
+
+	/**
+	 * Returns the parser associated with this marshall.
+	 *
+	 * @return The parser associated with this marshall.
+	 */
+	public Parser getParser() {
+		return p;
+	}
+
+	/**
 	 * Serializes a POJO directly to either a <code>String</code> or <code><jk>byte</jk>[]</code> depending on the serializer type.
 	 *
 	 * @param o The object to serialize.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/pojotools/TimeMatcherFactory.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/pojotools/TimeMatcherFactory.java
index b27ea5b..9eb9263 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/pojotools/TimeMatcherFactory.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/pojotools/TimeMatcherFactory.java
@@ -312,7 +312,6 @@ public class TimeMatcherFactory extends MatcherFactory {
 			if (state == S01) {
 				// No tokens found.
 			} else if (state == S02 || state == S03 || state == S04 || state == S05 || state == S06 || state == S10 || state == S11 || state == S12) {
-				System.err.println("state=["+state+"]");
 				throw new PatternException("Invalid range pattern (E{0}): {1}", state, s);
 			} else if (state == S07) {
 				l.add(new TimestampRange(f, eq, s1));
@@ -361,8 +360,6 @@ public class TimeMatcherFactory extends MatcherFactory {
 		}
 
 		public TimestampRange(SimpleDateFormat[] formats, Equality eq, String singleDate) {
-			System.err.println("eq=["+eq+"], singleDate=["+singleDate+"]");
-
 			CalendarP singleDate1 = parseDate(formats, singleDate);
 			if (eq == Equality.GT) {
 				this.start = singleDate1.roll(1).roll(MILLISECOND, -1).getCalendar();
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/MockHttpConnection.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/MockHttpConnection.java
index b65adea..15b393c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/MockHttpConnection.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/MockHttpConnection.java
@@ -12,6 +12,8 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.utils;
 
+import java.util.*;
+
 /**
  * Represent the basic connection for mock HTTP requests.
  *
@@ -26,9 +28,10 @@ public interface MockHttpConnection {
 	 *
 	 * @param method The HTTP request method.
 	 * @param path The HTTP request path.
+	 * @param headers Optional HTTP request headers.
 	 * @param body The HTTP request body.
 	 * @return A new mock request.
 	 * @throws Exception
 	 */
-	MockHttpRequest request(String method, String path, Object body) throws Exception;
+	MockHttpRequest request(String method, String path, Map<String,Object> headers, Object body) throws Exception;
 }
diff --git a/juneau-doc/docs/ReleaseNotes/8.0.1.html b/juneau-doc/docs/ReleaseNotes/8.0.1.html
index 7cebcb0..25394a7 100644
--- a/juneau-doc/docs/ReleaseNotes/8.0.1.html
+++ b/juneau-doc/docs/ReleaseNotes/8.0.1.html
@@ -58,3 +58,8 @@
 		HTML widgets now have access to the <code>RestResponse</code> object if they need access to the output bean.
 </ul>
 
+<h5 class='topic w800'>juneau-rest-client</h5>
+<ul class='spaced-list'>
+	<li>
+		PATCH support added.
+</ul>
\ No newline at end of file
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 4b23dcd..c5d6f49 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -35371,6 +35371,14 @@
 			<li class='jac'>{@link org.apache.juneau.rest.BasicRestJena} - Non-servlet equivalent to {@link org.apache.juneau.rest.BasicRestServletJena}
 			<li class='jac'>{@link org.apache.juneau.rest.BasicRestJenaGroup} - Non-servlet equivalent to {@link org.apache.juneau.rest.BasicRestServletJenaGroup}
 		</ul>
+	<li>
+		HTML widgets now have access to the <code>RestResponse</code> object if they need access to the output bean.
+</ul>
+
+<h5 class='topic w800'>juneau-rest-client</h5>
+<ul class='spaced-list'>
+	<li>
+		PATCH support added.
 </ul>
 </div><!-- END: 8.0.1 -->
 
diff --git a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/MockRestTest.java b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/MockRestTest.java
index 3ea3900..ac56130 100644
--- a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/MockRestTest.java
+++ b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/MockRestTest.java
@@ -45,14 +45,14 @@ public class MockRestTest {
 
 	@Test
 	public void a01() throws Exception {
-		MockRest a = MockRest.create(A.class);
+		MockRest a = MockRest.build(A.class, null);
 		RestClient rc = RestClient.create().mockHttpConnection(a).build();
 		assertEquals("OK", rc.doPut("/a01", "OK").getResponseAsString());
 	}
 
 	@Test
 	public void a02() throws Exception {
-		MockRest a = MockRest.create(A.class);
+		MockRest a = MockRest.build(A.class);
 		RestClient rc = RestClient.create().json().mockHttpConnection(a).build();
 		assertEquals("OK", rc.doPut("/a02", "OK").getResponse(String.class));
 	}
diff --git a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/CallbackStringsTest.java b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/CallbackStringsTest.java
index 9bb33ae..679cf84 100644
--- a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/CallbackStringsTest.java
+++ b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/CallbackStringsTest.java
@@ -50,7 +50,7 @@ public class CallbackStringsTest {
 			return m;
 		}
 	}
-	static RestClient a = RestClient.create().mockHttpConnection(MockRest.create(A.class)).build();
+	static RestClient a = RestClient.create().mockHttpConnection(MockRest.build(A.class, null)).build();
 
 	@Test
 	public void a01() throws Exception {
diff --git a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/ClientFuturesTest.java b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/ClientFuturesTest.java
index 79812fa..53ce031 100644
--- a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/ClientFuturesTest.java
+++ b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/ClientFuturesTest.java
@@ -39,7 +39,7 @@ public class ClientFuturesTest {
 			return new ObjectMap().append("foo","bar");
 		}
 	}
-	static RestClient a = RestClient.create().mockHttpConnection(MockRest.create(A.class)).build();
+	static RestClient a = RestClient.create().mockHttpConnection(MockRest.build(A.class, null)).build();
 
 	@Test
 	public void a01() throws Exception {
diff --git a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/FormDataTest.java b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/FormDataTest.java
index 0ed3e18..b34642a 100644
--- a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/FormDataTest.java
+++ b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/FormDataTest.java
@@ -41,7 +41,7 @@ public class FormDataTest extends RestTestcase {
 			return new StringReader("Content-Type=["+req.getContentType()+"], contents=["+read(req.getReader())+"]");
 		}
 	}
-	static RestClient a = RestClient.create().mockHttpConnection(MockRest.create(A.class)).build();
+	static RestClient a = RestClient.create().mockHttpConnection(MockRest.build(A.class)).build();
 
 	@Test
 	public void a01_formDataMethod() throws Exception {
@@ -61,7 +61,7 @@ public class FormDataTest extends RestTestcase {
 
 	@Test
 	public void a03_plainTextParams() throws Exception {
-		RestClient c = RestClient.create().mockHttpConnection(MockRest.create(A.class)).urlEnc().paramFormatPlain().build();
+		RestClient c = RestClient.create().mockHttpConnection(MockRest.build(A.class)).urlEnc().paramFormatPlain().build();
 		try {
 			String r;
 
diff --git a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/InterfaceProxyTest.java b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/InterfaceProxyTest.java
index 6ae83f4..c1b0a3f 100644
--- a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/InterfaceProxyTest.java
+++ b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/InterfaceProxyTest.java
@@ -935,7 +935,7 @@ public class InterfaceProxyTest {
 			};
 		}
 	}
-	static MockRest interfaceProxyResource = MockRest.create(InterfaceProxyResource.class);
+	static MockRest interfaceProxyResource = MockRest.build(InterfaceProxyResource.class);
 
 	private static Map<String,InterfaceProxy> cache = new LinkedHashMap<>();
 
diff --git a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/RequestBeanProxyTest.java b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/RequestBeanProxyTest.java
index 82dd337..d3ac26b 100644
--- a/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/RequestBeanProxyTest.java
+++ b/juneau-microservice/juneau-microservice-test/src/test/java/org/apache/juneau/rest/test/client/RequestBeanProxyTest.java
@@ -52,7 +52,7 @@ public class RequestBeanProxyTest {
 			return req.getQuery().toString(true);
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	//=================================================================================================================
 	// @Query - Simple values
@@ -341,7 +341,7 @@ public class RequestBeanProxyTest {
 			return req.getFormData().toString(true);
 		}
 	}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class, null);
 
 	//=================================================================================================================
 	// @FormData, Simple values
@@ -645,7 +645,7 @@ public class RequestBeanProxyTest {
 			return req.getHeaders().subset("a,b,c,d,e,f,g,h,i,a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4").toString(true);
 		}
 	}
-	static MockRest e = MockRest.create(E.class);
+	static MockRest e = MockRest.build(E.class, null);
 
 	//=================================================================================================================
 	// @Header, Simple values
@@ -898,7 +898,7 @@ public class RequestBeanProxyTest {
 			return req.getPathMatch().getRemainder();
 		}
 	}
-	static MockRest g = MockRest.create(G.class);
+	static MockRest g = MockRest.build(G.class, null);
 
 	//=================================================================================================================
 	// @Path, Simple values
diff --git a/juneau-rest/juneau-rest-client/pom.xml b/juneau-rest/juneau-rest-client/pom.xml
index 5f25376..f68e05d 100644
--- a/juneau-rest/juneau-rest-client/pom.xml
+++ b/juneau-rest/juneau-rest-client/pom.xml
@@ -62,7 +62,6 @@
 			<groupId>org.apache.juneau</groupId>
 			<artifactId>juneau-rest-server</artifactId>
 			<version>${project.version}</version>
-			<scope>test</scope>
 		</dependency>
 		<dependency>
 			<groupId>org.apache.juneau</groupId>
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index e47b84f..ae5eb33 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -39,6 +39,7 @@ import org.apache.juneau.remote.*;
 import org.apache.juneau.rest.client.remote.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.urlencoding.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Utility class for interfacing with remote REST interfaces.
@@ -399,6 +400,7 @@ public class RestClient extends BeanContext implements Closeable {
 	 */
 	public static final String RESTCLIENT_serializer = PREFIX + "serializer.o";
 
+	private static final Set<String> NO_BODY_METHODS = Collections.unmodifiableSet(ASet.<String>create("GET","HEAD","DELETE","CONNECT","OPTIONS","TRACE"));
 
 	private static final ConcurrentHashMap<Class,HttpPartSerializer> partSerializerCache = new ConcurrentHashMap<>();
 
@@ -536,6 +538,18 @@ public class RestClient extends BeanContext implements Closeable {
 	}
 
 	/**
+	 * Returns <jk>true</jk> if specified http method has content.
+	 * <p>
+	 * By default, anything not in this list can have content:  <code>GET, HEAD, DELETE, CONNECT, OPTIONS, TRACE</code>.
+	 *
+	 * @param httpMethod The HTTP method.  Must be upper-case.
+	 * @return <jk>true</jk> if specified http method has content.
+	 */
+	protected boolean hasContent(String httpMethod) {
+		return ! NO_BODY_METHODS.contains(httpMethod);
+	}
+
+	/**
 	 * Calls {@link CloseableHttpClient#close()} on the underlying {@link CloseableHttpClient}.
 	 *
 	 * <p>
@@ -754,6 +768,59 @@ public class RestClient extends BeanContext implements Closeable {
 	}
 
 	/**
+	 * Perform a <code>PATCH</code> request against the specified URL.
+	 *
+	 * @param url
+	 * 	The URL of the remote REST resource.
+	 * 	Can be any of the following:  {@link String}, {@link URI}, {@link URL}.
+	 * @param o
+	 * 	The object to serialize and transmit to the URL as the body of the request.
+	 * 	Can be of the following types:
+	 * 	<ul class='spaced-list'>
+	 * 		<li>
+	 * 			{@link Reader} - Raw contents of {@code Reader} will be serialized to remote resource.
+	 * 		<li>
+	 * 			{@link InputStream} - Raw contents of {@code InputStream} will be serialized to remote resource.
+	 * 		<li>
+	 * 			{@link Object} - POJO to be converted to text using the {@link Serializer} registered with the {@link RestClient}.
+	 * 		<li>
+	 * 			{@link HttpEntity} - Bypass Juneau serialization and pass HttpEntity directly to HttpClient.
+	 * 	</ul>
+	 * @return
+	 * 	A {@link RestCall} object that can be further tailored before executing the request and getting the response
+	 * 	as a parsed object.
+	 * @throws RestCallException If any authentication errors occurred.
+	 */
+	public RestCall doPatch(Object url, Object o) throws RestCallException {
+		return doCall("PATCH", url, true).body(o);
+	}
+
+	/**
+	 * Same as {@link #doPatch(Object, Object)} but don't specify the input yet.
+	 *
+	 * <p>
+	 * You must call either {@link RestCall#body(Object)} or {@link RestCall#formData(String, Object)} to set the
+	 * contents on the result object.
+	 *
+	 * <h5 class='section'>Notes:</h5>
+	 * <ul class='spaced-list'>
+	 * 	<li>Use {@link #doFormPost(Object, Object)} for <code>application/x-www-form-urlencoded</code> form posts.
+	 * </ul>
+	 *
+	 * @param url
+	 * 	The URL of the remote REST resource.
+	 * 	Can be any of the following:  {@link String}, {@link URI}, {@link URL}.
+	 * @return
+	 * 	A {@link RestCall} object that can be further tailored before executing the request and getting the response
+	 * 	as a parsed object.
+	 * @throws RestCallException
+	 */
+	public RestCall doPatch(Object url) throws RestCallException {
+		return doCall("PATCH", url, true);
+	}
+
+
+	/**
 	 * Performs a REST call where the entire call is specified in a simple string.
 	 *
 	 * <p>
@@ -1048,7 +1115,7 @@ public class RestClient extends BeanContext implements Closeable {
 						String httpMethod = rmm.getHttpMethod();
 						HttpPartSerializer s = getPartSerializer();
 
-						try (RestCall rc = doCall(httpMethod, url, httpMethod.equals("POST") || httpMethod.equals("PUT"))) {
+						try (RestCall rc = doCall(httpMethod, url, hasContent(httpMethod))) {
 
 							rc.serializer(serializer).parser(parser);
 
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
index 136593d..5ad6092 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClientBuilder.java
@@ -594,6 +594,19 @@ public class RestClientBuilder extends BeanContextBuilder {
 	//-----------------------------------------------------------------------------------------------------------------
 
 	/**
+	 * Sets arbitrary request headers.
+	 *
+	 * @param headers The headers to set on requests.
+	 * @return This object (for method chaining).
+	 */
+	public RestClientBuilder headers(Map<String,Object> headers) {
+		if (headers != null)
+			for (Map.Entry<String,Object> e : headers.entrySet())
+				header(e.getKey(), e.getValue());
+		return this;
+	}
+
+	/**
 	 * Sets the value for the <code>Accept</code> request header.
 	 *
 	 * <p>
@@ -2347,6 +2360,12 @@ public class RestClientBuilder extends BeanContextBuilder {
 	}
 
 	@Override /* BeanContextBuilder */
+	public RestClientBuilder debug(boolean value) {
+		super.debug(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
 	public <T> RestClientBuilder example(Class<T> c, T o) {
 		super.example(c, o);
 		return this;
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/mock/MockHttpClientConnection.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/mock/MockHttpClientConnection.java
index bcfdbd3..f3ea773 100644
--- a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/mock/MockHttpClientConnection.java
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/mock/MockHttpClientConnection.java
@@ -79,8 +79,8 @@ public class MockHttpClientConnection implements HttpClientConnection {
 	public void sendRequestHeader(HttpRequest request) throws HttpException, IOException {
 		try {
 			RequestLine rl = request.getRequestLine();
-			req = c.request(rl.getMethod(), rl.getUri(), null);
-			for (Header h : request.getAllHeaders())
+			req = c.request(rl.getMethod(), rl.getUri(), null, null);
+			for (Header h : request.getAllHeaders()) 
 				req.header(h.getName(), h.getValue());
 		} catch (Exception e) {
 			throw new HttpException(e.getMessage(), e);
diff --git a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/mock/MockRemoteResource.java b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/mock/MockRemoteResource.java
new file mode 100644
index 0000000..4ae5170
--- /dev/null
+++ b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/mock/MockRemoteResource.java
@@ -0,0 +1,404 @@
+// ***************************************************************************************************************************
+// * 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.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.rest.client.mock;
+
+import java.util.*;
+
+import org.apache.juneau.json.*;
+import org.apache.juneau.marshall.*;
+import org.apache.juneau.parser.*;
+import org.apache.juneau.rest.client.*;
+import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.serializer.*;
+
+/**
+ * Creates a mocked interface against a REST resource class to use for creating test remote resource interfaces.
+ *
+ * <h5 class='section'>See Also:</h5>
+ * <ul>
+ * 	<li class='link'>{@doc juneau-rest-server.UnitTesting}
+ * 	<li class='link'>{@doc juneau-rest-client.UnitTesting}
+ * </ul>
+ *
+ * @param <T> The interface class.
+ */
+public class MockRemoteResource<T> {
+
+	private MockRest.Builder mrb = MockRest.create();
+	private final Class<T> intf;
+	private Serializer s = JsonSerializer.DEFAULT;
+	private Parser p = JsonParser.DEFAULT;
+	private boolean debug;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param intf The remote interface.
+	 * @param impl The REST implementation class or bean.
+	 */
+	protected MockRemoteResource(Class<T> intf, Object impl) {
+		this.intf = intf;
+		mrb.impl(impl);
+	}
+
+	/**
+	 * Create a new builder using the specified remote resource interface and REST implementation class.
+	 *
+	 * @param intf The remote interface.
+	 * @param impl The REST implementation class.
+	 * @return A new builder.
+	 */
+	public static <T> MockRemoteResource<T> create(Class<T> intf, Class<?> impl) {
+		return new MockRemoteResource<>(intf, impl);
+	}
+
+	/**
+	 * Create a new builder using the specified remote resource interface and REST implementation bean.
+	 *
+	 * @param intf The remote interface.
+	 * @param impl The REST implementation bean.
+	 * @return A new builder.
+	 */
+	public static <T> MockRemoteResource<T> create(Class<T> intf, Object impl) {
+		return new MockRemoteResource<>(intf, impl);
+	}
+
+	/**
+	 * Constructs a remote proxy interface based on the settings of this builder.
+	 *
+	 * @return A new remote proxy interface.
+	 */
+	public T build() {
+		MockRest mr = mrb.build();
+		return RestClient.create(s, p).debug(debug).mockHttpConnection(mr).headers(mr.getHeaders()).build().getRemoteResource(intf);
+	}
+
+	/**
+	 * Convenience method for getting a remote resource interface.
+	 *
+	 * <p>
+	 * Equivalent to calling the following:
+	 * <p class='bcode w800'>
+	 * 	MockRemoteResource.<jsf>create</jsf>(intf, impl).build();
+	 * </p>
+	 *
+	 * <p>
+	 * Uses JSON serialization and parsing.
+	 *
+	 * @param intf The remote proxy interface class.
+	 * @param impl The REST implementation class.
+	 * @return A new proxy interface.
+	 */
+	public static <T> T build(Class<T> intf, Class<?> impl) {
+		return create(intf, impl).build();
+	}
+
+	/**
+	 * Convenience method for getting a remote resource interface.
+	 *
+	 * <p>
+	 * Equivalent to calling the following:
+	 * <p class='bcode w800'>
+	 * 	MockRemoteResource.<jsf>create</jsf>(intf, impl).serializer(s).parser(p).build();
+	 * </p>
+	 *
+	 * @param intf The remote proxy interface class.
+	 * @param impl The REST implementation class.
+	 * @param s
+	 * 	The serializer to use for serializing request bodies.
+	 * 	<br>Can be <jk>null</jk> to force no serializer to be used and no <code>Content-Type</code> header.
+	 * @param p
+	 * 	The parser to use for parsing response bodies.
+	 * 	<br>Can be <jk>null</jk> to force no parser to be used and no <code>Accept</code> header.
+	 * @return A new proxy interface.
+	 */
+	public static <T> T build(Class<T> intf, Class<?> impl, Serializer s, Parser p) {
+		return create(intf, impl).serializer(s).parser(p).build();
+	}
+
+	/**
+	 * Convenience method for getting a remote resource interface.
+	 *
+	 * <p>
+	 * Equivalent to calling the following:
+	 * <p class='bcode w800'>
+	 * 	MockRemoteResource.<jsf>create</jsf>(intf, impl).marshall(m).build();
+	 * </p>
+	 *
+	 * @param intf The remote proxy interface class.
+	 * @param impl The REST implementation class.
+	 * @param m
+	 * 	The marshall to use for serializing request bodies and parsing response bodies.
+	 * 	<br>Can be <jk>null</jk> to force no serializer or parser to be used and no <code>Accept</code> or <code>Content-Type</code> header.
+	 * @return A new proxy interface.
+	 */
+	public static <T> T build(Class<T> intf, Class<?> impl, Marshall m) {
+		return create(intf, impl).marshall(m).build();
+	}
+
+	/**
+	 * Convenience method for getting a remote resource interface.
+	 *
+	 * <p>
+	 * Equivalent to calling the following:
+	 * <p class='bcode w800'>
+	 * 	MockRemoteResource.<jsf>create</jsf>(intf, impl).build();
+	 * </p>
+	 *
+	 * <p>
+	 * Uses JSON serialization and parsing.
+	 *
+	 * @param intf The remote proxy interface class.
+	 * @param impl The REST implementation bean.
+	 * @return A new proxy interface.
+	 */
+	public static <T> T build(Class<T> intf, Object impl) {
+		return create(intf, impl).build();
+	}
+
+	/**
+	 * Convenience method for getting a remote resource interface.
+	 *
+	 * <p>
+	 * Equivalent to calling the following:
+	 * <p class='bcode w800'>
+	 * 	MockRemoteResource.<jsf>create</jsf>(intf, impl).serializer(s).parser(p).build();
+	 * </p>
+	 *
+	 * @param intf The remote proxy interface class.
+	 * @param impl The REST implementation object.
+	 * @param s The serializer to use for serializing request bodies.
+	 * @param p The parser to use for parsing response bodies.
+	 * @return A new proxy interface.
+	 */
+	public static <T> T build(Class<T> intf, Object impl, Serializer s, Parser p) {
+		return create(intf, impl).serializer(s).parser(p).build();
+	}
+
+	/**
+	 * Convenience method for getting a remote resource interface.
+	 *
+	 * <p>
+	 * Equivalent to calling the following:
+	 * <p class='bcode w800'>
+	 * 	MockRemoteResource.<jsf>create</jsf>(intf, impl).marshall(m).build();
+	 * </p>
+	 *
+	 * @param intf The remote proxy interface class.
+	 * @param impl The REST implementation object.
+	 * @param m The marshall to use for serializing request bodies and parsing response bodies.
+	 * @return A new proxy interface.
+	 */
+	public static <T> T build(Class<T> intf, Object impl, Marshall m) {
+		return create(intf, impl).marshall(m).build();
+	}
+
+	/**
+	 * Enable debug mode.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> debug() {
+		mrb.debug();
+		this.debug = true;
+		return this;
+	}
+
+	/**
+	 * Adds a header to every request.
+	 *
+	 * @param name The header name.
+	 * @param value
+	 * 	The header value.
+	 * 	<br>Can be <jk>null</jk> (will be skipped).
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> header(String name, Object value) {
+		mrb.header(name, value);
+		return this;
+	}
+
+	/**
+	 * Adds the specified headers to every request.
+	 *
+	 * @param value
+	 * 	The header values.
+	 * 	<br>Can be <jk>null</jk> (existing values will be cleared).
+	 * 	<br><jk>null</jk> null map values will be ignored.
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> headers(Map<String,Object> value) {
+		mrb.headers(value);
+		return this;
+	}
+
+	/**
+	 * Adds an <code>Accept</code> header to every request.
+	 *
+	 * @param value The <code>Accept/code> header value.
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> accept(String value) {
+		mrb.accept(value);
+		return this;
+	}
+
+	/**
+	 * Adds a <code>Content-Type</code> header to every request.
+	 *
+	 * @param value The <code>Content-Type</code> header value.
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> contentType(String value) {
+		mrb.contentType(value);
+		return this;
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"application/json"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> json() {
+		marshall(Json.DEFAULT);
+		return this;
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"application/json+simple"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> simpleJson() {
+		marshall(SimpleJson.DEFAULT);
+		return this;
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/xml"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> xml() {
+		marshall(Xml.DEFAULT);
+		return this;
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/html"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> html() {
+		marshall(Html.DEFAULT);
+		return this;
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/plain"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> plainText() {
+		marshall(PlainText.DEFAULT);
+		return this;
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"octal/msgpack"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> msgpack() {
+		marshall(MsgPack.DEFAULT);
+		return this;
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/uon"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> uon() {
+		marshall(Uon.DEFAULT);
+		return this;
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"application/x-www-form-urlencoded"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> urlEnc() {
+		marshall(UrlEncoding.DEFAULT);
+		return this;
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/openapi"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> openapi() {
+		marshall(OpenApi.DEFAULT);
+		return this;
+	}
+
+	/**
+	 * Associates the specified {@link Marshall} with this client.
+	 *
+	 * <p>
+	 * This is shorthand for calling <code>serializer(x)</code> and <code>parser(x)</code> using the inner
+	 * serializer and parser of the marshall object.
+	 *
+	 * @param value
+	 * 	The marshall to use for serializing and parsing HTTP bodies.
+	 * 	<br>Can be <jk>null</jk> (will remote the existing serializer/parser).
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> marshall(Marshall value) {
+		if (value != null)
+			serializer(value.getSerializer()).parser(value.getParser());
+		else
+			serializer(null).parser(null);
+		return this;
+	}
+
+	/**
+	 * Associates the specified {@link Serializer} with this client.
+	 *
+	 * @param value
+	 * 	The serializer to use for serializing HTTP bodies.
+	 * 	<br>Can be <jk>null</jk> (will remote the existing serializer).
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> serializer(Serializer value) {
+		this.s = value;
+		contentType(value == null ? null : value.getPrimaryMediaType().toString());
+		return this;
+	}
+
+	/**
+	 * Associates the specified {@link Parser} with this client.
+	 *
+	 * @param value
+	 * 	The parser to use for parsing HTTP bodies.
+	 * 	<br>Can be <jk>null</jk> (will remote the existing parser).
+	 * @return This object (for method chaining).
+	 */
+	public MockRemoteResource<T> parser(Parser value) {
+		this.p = value;
+		accept(value == null ? null : value.getPrimaryMediaType().toString());
+		return this;
+	}
+}
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/BodyAnnotationTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/BodyAnnotationTest.java
index 2aa7581..4946425 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/BodyAnnotationTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/BodyAnnotationTest.java
@@ -27,7 +27,7 @@ import org.apache.juneau.marshall.*;
 import org.apache.juneau.oapi.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
-import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.apache.juneau.utils.*;
 import org.junit.*;
 import org.junit.runners.*;
@@ -115,7 +115,6 @@ public class BodyAnnotationTest {
 			return IOUtils.read(b);
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
 
 	@RemoteResource
 	public static interface A01 {
@@ -131,7 +130,7 @@ public class BodyAnnotationTest {
 		String postA10(@Body NameValuePairs b);
 	}
 
-	private static A01 a01 = RestClient.create().mockHttpConnection(a).serializer(JsonSerializer.class).build().getRemoteResource(A01.class);
+	private static A01 a01 = MockRemoteResource.create(A01.class, A.class).parser(null).build();
 
 	@Test
 	public void a01_int() throws Exception {
@@ -241,8 +240,6 @@ public class BodyAnnotationTest {
 			return b;
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
-
 	@RemoteResource
 	public static interface B01 {
 		String postB01(@Body int b);
@@ -257,7 +254,7 @@ public class BodyAnnotationTest {
 		String postB10(@Body NameValuePairs b);
 	}
 
-	private static B01 b01 = RestClient.create().openapi().mockHttpConnection(b).build().getRemoteResource(B01.class);
+	private static B01 b01 = MockRemoteResource.create(B01.class, B.class).marshall(OpenApi.DEFAULT).contentType(null).build();
 
 	@Test
 	public void b01_int() throws Exception {
@@ -368,8 +365,6 @@ public class BodyAnnotationTest {
 			return b;
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
-
 	@RemoteResource
 	public static interface C01 {
 		String postC01(@Body int b);
@@ -384,7 +379,7 @@ public class BodyAnnotationTest {
 		String postC10(@Body NameValuePairs b);
 	}
 
-	private static C01 c01 = RestClient.create().mockHttpConnection(c).contentType("text/foo").build().getRemoteResource(C01.class);
+	private static C01 c01 = MockRemoteResource.create(C01.class, C.class).serializer(null).contentType("text/foo").build();
 
 	@Test
 	public void c01_int() throws Exception {
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/EndToEndInterfaceTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/EndToEndInterfaceTest.java
index 987c5e4..4428c6d 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/EndToEndInterfaceTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/EndToEndInterfaceTest.java
@@ -24,8 +24,10 @@ import org.apache.juneau.http.annotation.Header;
 import org.apache.juneau.http.annotation.Query;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
+import org.apache.juneau.marshall.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.apache.juneau.rest.exception.*;
 import org.apache.juneau.rest.helper.*;
 import org.apache.juneau.rest.mock.*;
@@ -80,8 +82,7 @@ public class EndToEndInterfaceTest {
 		}
 	}
 
-	private static MockRest a = MockRest.create(A.class);
-	private static IA ia = RestClient.create().json().mockHttpConnection(a).build().getRemoteResource(IA.class);
+	private static IA ia = MockRemoteResource.build(IA.class, A.class, Json.DEFAULT);
 
 	@Test
 	public void a01_splitAnnotations_Body() throws Exception {
@@ -135,8 +136,7 @@ public class EndToEndInterfaceTest {
 		}
 	}
 
-	private static MockRest b = MockRest.create(B.class);
-	private static IB ib = RestClient.create().json().mockHttpConnection(b).build().getRemoteResource(IB.class);
+	private static IB ib = MockRemoteResource.build(IB.class, B.class);
 
 	@Test
 	public void b01_combinedAnnotations_Body() throws Exception {
@@ -207,7 +207,7 @@ public class EndToEndInterfaceTest {
 		@Override public UseProxy useProxy() { return UseProxy.INSTANCE; }
 	}
 
-	private static IC ic = RestClient.create().json().disableRedirectHandling().mockHttpConnection(MockRest.create(C.class)).build().getRemoteResource(IC.class);
+	private static IC ic = RestClient.create().json().disableRedirectHandling().mockHttpConnection(MockRest.create(C.class).build()).build().getRemoteResource(IC.class);
 
 	@Test
 	public void c01_standardResponses_Ok() throws Exception {
@@ -326,7 +326,7 @@ public class EndToEndInterfaceTest {
 		}
 	}
 
-	private static ID id = RestClient.create().json().mockHttpConnection(MockRest.create(D.class)).build().getRemoteResource(ID.class);
+	private static ID id = MockRemoteResource.build(ID.class, D.class);
 
 	@Test
 	public void d01_StreamResource() throws Exception {
@@ -344,7 +344,7 @@ public class EndToEndInterfaceTest {
 		assertEquals("text/foo", r.getMediaType().toString());
 	}
 
-	private static ID id2 = RestClient.create().mockHttpConnection(MockRest.create(D.class)).build().getRemoteResource(ID.class);
+	private static ID id2 = MockRemoteResource.build(ID.class, D.class);
 
 	@Test
 	public void d03_StreamResource_noMediaTypes() throws Exception {
@@ -539,7 +539,7 @@ public class EndToEndInterfaceTest {
 		}
 	}
 
-	private static IE iea = RestClient.create().json().mockHttpConnection(MockRest.create(EA.class)).build().getRemoteResource(IE.class);
+	private static IE iea = MockRemoteResource.build(IE.class, EA.class);
 
 	@Test
 	public void ea01_badRequest() {
@@ -974,7 +974,7 @@ public class EndToEndInterfaceTest {
 		}
 	}
 
-	private static IE ieb = RestClient.create().json().mockHttpConnection(MockRest.create(EB.class)).build().getRemoteResource(IE.class);
+	private static IE ieb = MockRemoteResource.build(IE.class, EB.class);
 
 	@Test
 	public void eb01_badRequest() {
@@ -1451,7 +1451,7 @@ public class EndToEndInterfaceTest {
 		}
 	}
 
-	private static IF ifa = RestClient.create().json().mockHttpConnection(MockRest.create(F.class)).build().getRemoteResource(IF.class);
+	private static IF ifa = MockRemoteResource.build(IF.class, F.class);
 
 	@Test
 	public void fa01_badRequest() {
@@ -1607,7 +1607,7 @@ public class EndToEndInterfaceTest {
 		}
 	}
 
-	private static IG ig = RestClient.create().json().mockHttpConnection(MockRest.create(G.class)).build().getRemoteResource(IG.class);
+	private static IG ig = MockRemoteResource.build(IG.class, G.class);
 
 	@Test
 	public void g01_reader() throws Exception {
@@ -1635,7 +1635,7 @@ public class EndToEndInterfaceTest {
 		}
 	}
 
-	private static IH ih = RestClient.create().json().disableRedirectHandling().mockHttpConnection(MockRest.create(H.class)).build().getRemoteResource(IH.class);
+	private static IH ih = RestClient.create().json().disableRedirectHandling().mockHttpConnection(MockRest.create(H.class).build()).build().getRemoteResource(IH.class);
 
 	@Test
 	public void h01_seeOtherRoot() throws Exception {
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/FormDataAnnotationTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/FormDataAnnotationTest.java
index e26b4e6..e131d74 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/FormDataAnnotationTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/FormDataAnnotationTest.java
@@ -27,7 +27,7 @@ import org.apache.juneau.http.annotation.Header;
 import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
-import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.apache.juneau.rest.testutils.*;
 import org.apache.juneau.utils.*;
 import org.junit.*;
@@ -62,7 +62,6 @@ public class FormDataAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
 
 	@RemoteResource
 	public static interface AR {
@@ -88,7 +87,7 @@ public class FormDataAnnotationTest {
 		@RemoteMethod(path="a") String postA09b(@FormData NameValuePairs b);
 	}
 
-	private static AR ar = RestClient.create().mockHttpConnection(a).build().getRemoteResource(AR.class);
+	private static AR ar = MockRemoteResource.build(AR.class, A.class, null);
 
 	@Test
 	public void a01_int() throws Exception {
@@ -182,7 +181,6 @@ public class FormDataAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
 
 	@RemoteResource
 	public static interface BR {
@@ -192,7 +190,7 @@ public class FormDataAnnotationTest {
 		@RemoteMethod(path="/") String postB04(@FormData(name="x",_default="",allowEmptyValue=true) String b);
 	}
 
-	private static BR br = RestClient.create().mockHttpConnection(b).build().getRemoteResource(BR.class);
+	private static BR br = MockRemoteResource.build(BR.class, B.class, null);
 
 	@Test
 	public void b01a_default() throws Exception {
@@ -250,7 +248,6 @@ public class FormDataAnnotationTest {
 			return b;
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
 
 	@RemoteResource
 	public static interface CR {
@@ -270,7 +267,7 @@ public class FormDataAnnotationTest {
 		@RemoteMethod(path="/b") String postC07b(@FormData(name="x",collectionFormat="uon") String...b);
 	}
 
-	private static CR cr = RestClient.create().mockHttpConnection(c).build().getRemoteResource(CR.class);
+	private static CR cr = MockRemoteResource.build(CR.class, C.class, null);
 
 	@Test
 	public void c01a_default() throws Exception {
@@ -342,7 +339,6 @@ public class FormDataAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest d = MockRest.create(D.class);
 
 	@RemoteResource
 	public static interface DR {
@@ -391,7 +387,7 @@ public class FormDataAnnotationTest {
 		@RemoteMethod(path="/") String postC16c(@FormData(name="x",minimum="1",maximum="10",exclusiveMinimum=true,exclusiveMaximum=true) Byte b);
 	}
 
-	private static DR dr = RestClient.create().mockHttpConnection(d).build().getRemoteResource(DR.class);
+	private static DR dr = MockRemoteResource.build(DR.class, D.class, null);
 
 	@Test
 	public void d01a_int_defaultExclusive() throws Exception {
@@ -717,7 +713,6 @@ public class FormDataAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest e = MockRest.create(E.class);
 
 	@RemoteResource
 	public static interface ER {
@@ -729,7 +724,7 @@ public class FormDataAnnotationTest {
 		@RemoteMethod(path="/") String postE06(@FormData(name="x",items=@Items(collectionFormat="pipes",uniqueItems=true)) String[]...b);
 	}
 
-	private static ER er = RestClient.create().mockHttpConnection(e).build().getRemoteResource(ER.class);
+	private static ER er = MockRemoteResource.build(ER.class, E.class, null);
 
 	@Test
 	public void e01_minMax() throws Exception {
@@ -777,7 +772,6 @@ public class FormDataAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest f = MockRest.create(F.class);
 
 	@RemoteResource
 	public static interface FR {
@@ -789,7 +783,7 @@ public class FormDataAnnotationTest {
 		@RemoteMethod(path="/") String postF06(@FormData(name="x",collectionFormat="pipes",items=@Items(pattern="foo\\d{1,3}")) String...b);
 	}
 
-	private static FR fr = RestClient.create().mockHttpConnection(f).build().getRemoteResource(FR.class);
+	private static FR fr = MockRemoteResource.build(FR.class, F.class, null);
 
 	@Test
 	public void f01_minMaxLength() throws Exception {
@@ -843,7 +837,6 @@ public class FormDataAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest g = MockRest.create(G.class);
 
 	@RemoteResource
 	public static interface GR {
@@ -863,7 +856,7 @@ public class FormDataAnnotationTest {
 		@RemoteMethod(path="/") String postG16(@FormData(name="x",multipleOf="2") Byte b);
 	}
 
-	private static GR gr = RestClient.create().mockHttpConnection(g).build().getRemoteResource(GR.class);
+	private static GR gr = MockRemoteResource.build(GR.class, G.class, null);
 
 	@Test
 	public void g01_multipleOf_int() throws Exception {
@@ -947,7 +940,6 @@ public class FormDataAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest h = MockRest.create(H.class);
 
 	@RemoteResource
 	public static interface HR {
@@ -956,7 +948,7 @@ public class FormDataAnnotationTest {
 		@RemoteMethod(path="/") String postH03(@FormData(name="x",required=true) String b);
 	}
 
-	private static HR hr = RestClient.create().mockHttpConnection(h).build().getRemoteResource(HR.class);
+	private static HR hr = MockRemoteResource.build(HR.class, H.class, null);
 
 	@Test
 	public void h01_required_default() throws Exception {
@@ -983,7 +975,6 @@ public class FormDataAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest i = MockRest.create(I.class);
 
 	@RemoteResource
 	public static interface IR {
@@ -992,7 +983,7 @@ public class FormDataAnnotationTest {
 		@RemoteMethod(path="/") String postI03(@FormData(name="x",skipIfEmpty=true) String b);
 	}
 
-	private static IR ir = RestClient.create().mockHttpConnection(i).build().getRemoteResource(IR.class);
+	private static IR ir = MockRemoteResource.build(IR.class, I.class, null);
 
 	@Test
 	public void h01_skipIfEmpty_default() throws Exception {
@@ -1018,14 +1009,13 @@ public class FormDataAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest j = MockRest.create(J.class);
 
 	@RemoteResource
 	public static interface JR {
 		@RemoteMethod(path="/") String postJ01(@FormData(name="x",serializer=XPartSerializer.class) String b);
 	}
 
-	private static JR jr = RestClient.create().mockHttpConnection(j).build().getRemoteResource(JR.class);
+	private static JR jr = MockRemoteResource.build(JR.class, J.class, null);
 
 	@Test
 	public void j01_serializer() throws Exception {
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/HeaderAnnotationTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/HeaderAnnotationTest.java
index 8b1eeaf..4fbc731 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/HeaderAnnotationTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/HeaderAnnotationTest.java
@@ -25,7 +25,7 @@ import org.apache.juneau.http.annotation.Header;
 import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
-import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.apache.juneau.rest.testutils.*;
 import org.apache.juneau.utils.*;
 import org.junit.*;
@@ -60,7 +60,6 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
 
 	@RemoteResource
 	public static interface A01 {
@@ -82,7 +81,7 @@ public class HeaderAnnotationTest {
 		@RemoteMethod(path="a") String getA09b(@Header NameValuePairs b);
 	}
 
-	private static A01 a01 = RestClient.create().mockHttpConnection(a).build().getRemoteResource(A01.class);
+	private static A01 a01 = MockRemoteResource.build(A01.class, A.class, null);
 
 	@Test
 	public void a01_int() throws Exception {
@@ -161,7 +160,6 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
 
 	@RemoteResource
 	public static interface BR {
@@ -171,7 +169,7 @@ public class HeaderAnnotationTest {
 		@RemoteMethod(path="/") String getB04(@Header(name="x",_default="",allowEmptyValue=true) String b);
 	}
 
-	private static BR br = RestClient.create().mockHttpConnection(b).build().getRemoteResource(BR.class);
+	private static BR br = MockRemoteResource.build(BR.class, B.class, null);
 
 	@Test
 	public void b01a_default() throws Exception {
@@ -226,7 +224,6 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
 
 	@RemoteResource
 	public static interface CR {
@@ -239,7 +236,7 @@ public class HeaderAnnotationTest {
 		@RemoteMethod(path="/a") String getC07(@Header(name="x",collectionFormat="uon") String...b);
 	}
 
-	private static CR cr = RestClient.create().mockHttpConnection(c).build().getRemoteResource(CR.class);
+	private static CR cr = MockRemoteResource.build(CR.class, C.class, null);
 
 	@Test
 	public void c01a_default() throws Exception {
@@ -283,7 +280,6 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest d = MockRest.create(D.class);
 
 	@RemoteResource
 	public static interface DR {
@@ -331,7 +327,7 @@ public class HeaderAnnotationTest {
 		@RemoteMethod(path="/") String getC16c(@Header(name="x",minimum="1",maximum="10",exclusiveMinimum=true,exclusiveMaximum=true) Byte b);
 	}
 
-	private static DR dr = RestClient.create().mockHttpConnection(d).build().getRemoteResource(DR.class);
+	private static DR dr = MockRemoteResource.build(DR.class, D.class, null);
 
 	@Test
 	public void d01a_int_defaultExclusive() throws Exception {
@@ -658,7 +654,6 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest e = MockRest.create(E.class);
 
 	@RemoteResource
 	public static interface ER {
@@ -670,7 +665,7 @@ public class HeaderAnnotationTest {
 		@RemoteMethod(path="/") String getE06(@Header(name="x",items=@Items(collectionFormat="pipes",uniqueItems=true)) String[]...b);
 	}
 
-	private static ER er = RestClient.create().mockHttpConnection(e).build().getRemoteResource(ER.class);
+	private static ER er = MockRemoteResource.build(ER.class, E.class, null);
 
 	@Test
 	public void e01_minMax() throws Exception {
@@ -719,7 +714,6 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest f = MockRest.create(F.class);
 
 	@RemoteResource
 	public static interface FR {
@@ -731,7 +725,7 @@ public class HeaderAnnotationTest {
 		@RemoteMethod(path="/") String getF06(@Header(name="x",collectionFormat="pipes",items=@Items(pattern="foo\\d{1,3}")) String...b);
 	}
 
-	private static FR fr = RestClient.create().mockHttpConnection(f).build().getRemoteResource(FR.class);
+	private static FR fr = MockRemoteResource.build(FR.class, F.class, null);
 
 	@Test
 	public void f01_minMaxLength() throws Exception {
@@ -786,7 +780,6 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest g = MockRest.create(G.class);
 
 	@RemoteResource
 	public static interface GR {
@@ -806,7 +799,7 @@ public class HeaderAnnotationTest {
 		@RemoteMethod(path="/") String getG16(@Header(name="x",multipleOf="2") Byte b);
 	}
 
-	private static GR gr = RestClient.create().mockHttpConnection(g).build().getRemoteResource(GR.class);
+	private static GR gr = MockRemoteResource.build(GR.class, G.class, null);
 
 	@Test
 	public void g01_multipleOf_int() throws Exception {
@@ -891,7 +884,6 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest h = MockRest.create(H.class);
 
 	@RemoteResource
 	public static interface HR {
@@ -900,7 +892,7 @@ public class HeaderAnnotationTest {
 		@RemoteMethod(path="/") String getH03(@Header(name="x",required=true) String b);
 	}
 
-	private static HR hr = RestClient.create().mockHttpConnection(h).build().getRemoteResource(HR.class);
+	private static HR hr = MockRemoteResource.build(HR.class, H.class, null);
 
 	@Test
 	public void h01_required_default() throws Exception {
@@ -928,7 +920,6 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest i = MockRest.create(I.class);
 
 	@RemoteResource
 	public static interface IR {
@@ -937,7 +928,7 @@ public class HeaderAnnotationTest {
 		@RemoteMethod(path="/") String getI03(@Header(name="x",skipIfEmpty=true) String b);
 	}
 
-	private static IR ir = RestClient.create().mockHttpConnection(i).build().getRemoteResource(IR.class);
+	private static IR ir = MockRemoteResource.build(IR.class, I.class, null);
 
 	@Test
 	public void h01_skipIfEmpty_default() throws Exception {
@@ -964,14 +955,13 @@ public class HeaderAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest j = MockRest.create(J.class);
 
 	@RemoteResource
 	public static interface JR {
 		@RemoteMethod(path="/") String getJ01(@Header(name="x",serializer=XPartSerializer.class) String b);
 	}
 
-	private static JR jr = RestClient.create().mockHttpConnection(j).build().getRemoteResource(JR.class);
+	private static JR jr = MockRemoteResource.build(JR.class, J.class, null);
 
 	@Test
 	public void j01_serializer() throws Exception {
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/PathAnnotationTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/PathAnnotationTest.java
index 7d52bf3..2fe42f2 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/PathAnnotationTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/PathAnnotationTest.java
@@ -25,7 +25,7 @@ import org.apache.juneau.http.annotation.Path;
 import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
-import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.apache.juneau.rest.testutils.*;
 import org.apache.juneau.utils.*;
 import org.junit.*;
@@ -59,7 +59,6 @@ public class PathAnnotationTest {
 			return x.toString();
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
 
 	@RemoteResource
 	public static interface A01 {
@@ -81,7 +80,7 @@ public class PathAnnotationTest {
 		@RemoteMethod(path="a/{x}") String getA09b(@Path NameValuePairs b);
 	}
 
-	private static A01 a01 = RestClient.create().mockHttpConnection(a).build().getRemoteResource(A01.class);
+	private static A01 a01 = MockRemoteResource.build(A01.class, A.class, null);
 
 	@Test
 	public void a01_int() throws Exception {
@@ -160,7 +159,6 @@ public class PathAnnotationTest {
 			return x.toString();
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
 
 	@RemoteResource
 	public static interface CR {
@@ -173,7 +171,7 @@ public class PathAnnotationTest {
 		@RemoteMethod(path="/a/{x}") String getC07(@Path(name="x",collectionFormat="uon") String...b);
 	}
 
-	private static CR cr = RestClient.create().mockHttpConnection(c).build().getRemoteResource(CR.class);
+	private static CR cr = MockRemoteResource.build(CR.class, C.class, null);
 
 	@Test
 	public void c01a_default() throws Exception {
@@ -217,7 +215,6 @@ public class PathAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest d = MockRest.create(D.class);
 
 	@RemoteResource
 	public static interface DR {
@@ -265,7 +262,7 @@ public class PathAnnotationTest {
 		@RemoteMethod(path="/a/{x}") String getC16c(@Path(name="x",minimum="1",maximum="10",exclusiveMinimum=true,exclusiveMaximum=true) Byte b);
 	}
 
-	private static DR dr = RestClient.create().mockHttpConnection(d).build().getRemoteResource(DR.class);
+	private static DR dr = MockRemoteResource.build(DR.class, D.class, null);
 
 	@Test
 	public void d01a_int_defaultExclusive() throws Exception {
@@ -574,7 +571,6 @@ public class PathAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest e = MockRest.create(E.class);
 
 	@RemoteResource
 	public static interface ER {
@@ -586,7 +582,7 @@ public class PathAnnotationTest {
 		@RemoteMethod(path="/{x}") String getE06(@Path(name="x",items=@Items(collectionFormat="pipes",uniqueItems=true)) String[]...b);
 	}
 
-	private static ER er = RestClient.create().mockHttpConnection(e).build().getRemoteResource(ER.class);
+	private static ER er = MockRemoteResource.build(ER.class, E.class, null);
 
 	@Test
 	public void e01_minMax() throws Exception {
@@ -635,7 +631,6 @@ public class PathAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest f = MockRest.create(F.class);
 
 	@RemoteResource
 	public static interface FR {
@@ -647,7 +642,7 @@ public class PathAnnotationTest {
 		@RemoteMethod(path="/{x}") String getF06(@Path(name="x",collectionFormat="pipes",items=@Items(pattern="foo\\d{1,3}")) String...b);
 	}
 
-	private static FR fr = RestClient.create().mockHttpConnection(f).build().getRemoteResource(FR.class);
+	private static FR fr = MockRemoteResource.build(FR.class, F.class, null);
 
 	@Test
 	public void f01_minMaxLength() throws Exception {
@@ -699,7 +694,6 @@ public class PathAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest g = MockRest.create(G.class);
 
 	@RemoteResource
 	public static interface GR {
@@ -719,7 +713,7 @@ public class PathAnnotationTest {
 		@RemoteMethod(path="/{x}") String getG16(@Path(name="x",multipleOf="2") Byte b);
 	}
 
-	private static GR gr = RestClient.create().mockHttpConnection(g).build().getRemoteResource(GR.class);
+	private static GR gr = MockRemoteResource.build(GR.class, G.class, null);
 
 	@Test
 	public void g01_multipleOf_int() throws Exception {
@@ -804,14 +798,13 @@ public class PathAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest h = MockRest.create(H.class);
 
 	@RemoteResource
 	public static interface HR {
 		@RemoteMethod(path="/{x}") String getH01(@Path(name="x") String b);
 	}
 
-	private static HR hr = RestClient.create().mockHttpConnection(h).build().getRemoteResource(HR.class);
+	private static HR hr = MockRemoteResource.build(HR.class, H.class);
 
 	@Test
 	public void h01_required_default() throws Exception {
@@ -830,14 +823,13 @@ public class PathAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest j = MockRest.create(J.class);
 
 	@RemoteResource
 	public static interface JR {
 		@RemoteMethod(path="/{x}") String getJ01(@Path(name="x",serializer=XPartSerializer.class) String b);
 	}
 
-	private static JR jr = RestClient.create().mockHttpConnection(j).build().getRemoteResource(JR.class);
+	private static JR jr = MockRemoteResource.build(JR.class, J.class, null);
 
 	@Test
 	public void j01_serializer() throws Exception {
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/QueryAnnotationTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/QueryAnnotationTest.java
index 086b65f..61697f4 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/QueryAnnotationTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/QueryAnnotationTest.java
@@ -27,7 +27,7 @@ import org.apache.juneau.jsonschema.annotation.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
-import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.apache.juneau.rest.testutils.*;
 import org.apache.juneau.utils.*;
 import org.junit.*;
@@ -61,7 +61,6 @@ public class QueryAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
 
 	@RemoteResource
 	public static interface A01 {
@@ -87,7 +86,7 @@ public class QueryAnnotationTest {
 		@RemoteMethod(path="a") String getA09b(@Query NameValuePairs b);
 	}
 
-	private static A01 a01 = RestClient.create().mockHttpConnection(a).build().getRemoteResource(A01.class);
+	private static A01 a01 = MockRemoteResource.build(A01.class, A.class, null);
 
 	@Test
 	public void a01_int() throws Exception {
@@ -181,7 +180,6 @@ public class QueryAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
 
 	@RemoteResource
 	public static interface BR {
@@ -191,7 +189,7 @@ public class QueryAnnotationTest {
 		@RemoteMethod(path="/") String getB04(@Query(name="x",_default="",allowEmptyValue=true) String b);
 	}
 
-	private static BR br = RestClient.create().mockHttpConnection(b).build().getRemoteResource(BR.class);
+	private static BR br = MockRemoteResource.build(BR.class, B.class, null);
 
 	@Test
 	public void b01a_default() throws Exception {
@@ -249,7 +247,6 @@ public class QueryAnnotationTest {
 			return new StringReader(req.getQueryString());
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
 
 	@RemoteResource
 	public static interface CR {
@@ -269,7 +266,7 @@ public class QueryAnnotationTest {
 		@RemoteMethod(path="/b") String getC07b(@Query(name="x",collectionFormat="uon") String...b);
 	}
 
-	private static CR cr = RestClient.create().mockHttpConnection(c).build().getRemoteResource(CR.class);
+	private static CR cr = MockRemoteResource.build(CR.class, C.class, null);
 
 	@Test
 	public void c01a_default() throws Exception {
@@ -341,7 +338,6 @@ public class QueryAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest d = MockRest.create(D.class);
 
 	@RemoteResource
 	public static interface DR {
@@ -389,7 +385,7 @@ public class QueryAnnotationTest {
 		@RemoteMethod(path="/") String getC16c(@Query(name="x",minimum="1",maximum="10",exclusiveMinimum=true,exclusiveMaximum=true) Byte b);
 	}
 
-	private static DR dr = RestClient.create().mockHttpConnection(d).build().getRemoteResource(DR.class);
+	private static DR dr = MockRemoteResource.build(DR.class, D.class, null);
 
 	@Test
 	public void d01a_int_defaultExclusive() throws Exception {
@@ -715,7 +711,6 @@ public class QueryAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest e = MockRest.create(E.class);
 
 	@RemoteResource
 	public static interface ER {
@@ -727,7 +722,7 @@ public class QueryAnnotationTest {
 		@RemoteMethod(path="/") String getE06(@Query(name="x",items=@Items(collectionFormat="pipes",uniqueItems=true)) String[]...b);
 	}
 
-	private static ER er = RestClient.create().mockHttpConnection(e).build().getRemoteResource(ER.class);
+	private static ER er = MockRemoteResource.build(ER.class, E.class, null);
 
 	@Test
 	public void e01_minMax() throws Exception {
@@ -775,7 +770,6 @@ public class QueryAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest f = MockRest.create(F.class);
 
 	@RemoteResource
 	public static interface FR {
@@ -787,7 +781,7 @@ public class QueryAnnotationTest {
 		@RemoteMethod(path="/") String getF06(@Query(name="x",collectionFormat="pipes",items=@Items(pattern="foo\\d{1,3}")) String...b);
 	}
 
-	private static FR fr = RestClient.create().mockHttpConnection(f).build().getRemoteResource(FR.class);
+	private static FR fr = MockRemoteResource.build(FR.class, F.class, null);
 
 	@Test
 	public void f01_minMaxLength() throws Exception {
@@ -841,7 +835,6 @@ public class QueryAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest g = MockRest.create(G.class);
 
 	@RemoteResource
 	public static interface GR {
@@ -861,7 +854,7 @@ public class QueryAnnotationTest {
 		@RemoteMethod(path="/") String getG16(@Query(name="x",multipleOf="2") Byte b);
 	}
 
-	private static GR gr = RestClient.create().mockHttpConnection(g).build().getRemoteResource(GR.class);
+	private static GR gr = MockRemoteResource.build(GR.class, G.class, null);
 
 	@Test
 	public void g01_multipleOf_int() throws Exception {
@@ -945,7 +938,6 @@ public class QueryAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest h = MockRest.create(H.class);
 
 	@RemoteResource
 	public static interface HR {
@@ -954,7 +946,7 @@ public class QueryAnnotationTest {
 		@RemoteMethod(path="/") String getH03(@Query(name="x",required=true) String b);
 	}
 
-	private static HR hr = RestClient.create().mockHttpConnection(h).build().getRemoteResource(HR.class);
+	private static HR hr = MockRemoteResource.build(HR.class, H.class, null);
 
 	@Test
 	public void h01_required_default() throws Exception {
@@ -981,7 +973,6 @@ public class QueryAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest i = MockRest.create(I.class);
 
 	@RemoteResource
 	public static interface IR {
@@ -990,7 +981,7 @@ public class QueryAnnotationTest {
 		@RemoteMethod(path="/") String getI03(@Query(name="x",skipIfEmpty=true) String b);
 	}
 
-	private static IR ir = RestClient.create().mockHttpConnection(i).build().getRemoteResource(IR.class);
+	private static IR ir = MockRemoteResource.build(IR.class, I.class, null);
 
 	@Test
 	public void h01_skipIfEmpty_default() throws Exception {
@@ -1016,14 +1007,13 @@ public class QueryAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest j = MockRest.create(J.class);
 
 	@RemoteResource
 	public static interface JR {
 		@RemoteMethod(path="/") String getJ01(@Query(name="x",serializer=XPartSerializer.class) String b);
 	}
 
-	private static JR jr = RestClient.create().mockHttpConnection(j).build().getRemoteResource(JR.class);
+	private static JR jr = MockRemoteResource.build(JR.class, J.class, null);
 
 	@Test
 	public void j01_serializer() throws Exception {
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RemoteMethodAnnotationTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RemoteMethodAnnotationTest.java
index db1cc80..ea44020 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RemoteMethodAnnotationTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RemoteMethodAnnotationTest.java
@@ -21,10 +21,10 @@ import org.apache.juneau.http.annotation.Body;
 import org.apache.juneau.http.annotation.Response;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
+import org.apache.juneau.marshall.*;
 import org.apache.juneau.oapi.*;
 import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.client.*;
-import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.junit.*;
 import org.junit.runners.*;
 
@@ -61,8 +61,6 @@ public class RemoteMethodAnnotationTest {
 			return "qux";
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
-	private static RestClient ra = RestClient.create().mockHttpConnection(a).build();
 
 	@RemoteResource
 	public static interface A01 {
@@ -75,7 +73,7 @@ public class RemoteMethodAnnotationTest {
 
 	@Test
 	public void a01_inferredMethodsAndPaths() throws Exception {
-		A01 t = ra.getRemoteResource(A01.class);
+		A01 t = MockRemoteResource.build(A01.class, A.class, null);
 		assertEquals("foo", t.doGet());
 		assertEquals("foo", t.doGET());
 		assertEquals("qux", t.doFoo());
@@ -111,8 +109,6 @@ public class RemoteMethodAnnotationTest {
 			return "qux";
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
-	private static RestClient rb = RestClient.create().mockHttpConnection(b).build();
 
 	@RemoteResource
 	public static interface B01 {
@@ -126,7 +122,7 @@ public class RemoteMethodAnnotationTest {
 
 	@Test
 	public void b01_returnTypes() throws Exception {
-		B01 t = rb.getRemoteResource(B01.class);
+		B01 t = MockRemoteResource.build(B01.class, B.class, null);
 		t.b01();
 		assertEquals("foo", t.b02());
 		assertEquals("bar", IOUtils.read(t.b02a().getEntity().getContent()));
@@ -146,8 +142,6 @@ public class RemoteMethodAnnotationTest {
 			return body;
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
-	private static RestClient rc = RestClient.create().mockHttpConnection(c).simpleJson().build();
 
 	@RemoteResource
 	public static interface C01 {
@@ -167,7 +161,7 @@ public class RemoteMethodAnnotationTest {
 
 	@Test
 	public void c01_returnTypes_json() throws Exception {
-		C01 t = rc.getRemoteResource(C01.class);
+		C01 t = MockRemoteResource.build(C01.class, C.class, Json.DEFAULT);
 		assertEquals("foo", t.c01a("foo"));
 		assertEquals("'foo'", IOUtils.read(t.c01b("foo").getEntity().getContent()));
 		assertEquals("'foo'", IOUtils.read(t.c01c("foo")));
@@ -187,8 +181,6 @@ public class RemoteMethodAnnotationTest {
 			return body;
 		}
 	}
-	private static MockRest d = MockRest.create(D.class, true);
-	private static RestClient rd = RestClient.create().debug().mockHttpConnection(d).build();
 
 	@RemoteResource
 	public static interface D01 {
@@ -208,7 +200,7 @@ public class RemoteMethodAnnotationTest {
 
 	@Test
 	public void d01_returnTypes_partSerialization() throws Exception {
-		D01 t = rd.getRemoteResource(D01.class);
+		D01 t = MockRemoteResource.build(D01.class, D.class, OpenApi.DEFAULT);
 		assertEquals("foo", t.d01a("foo"));
 		assertEquals("foo", IOUtils.read(t.d01b("foo").getEntity().getContent()));
 		assertEquals("foo", IOUtils.read(t.d01c("foo")));
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RemoteResourceAnnotationTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RemoteResourceAnnotationTest.java
index bd8edac..8d0b2e7 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RemoteResourceAnnotationTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RemoteResourceAnnotationTest.java
@@ -16,6 +16,7 @@ import static org.junit.Assert.*;
 
 import org.apache.juneau.rest.annotation.*;
 import org.apache.juneau.rest.client.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.apache.juneau.rest.mock.*;
 import org.junit.*;
 import org.junit.runners.*;
@@ -49,8 +50,7 @@ public class RemoteResourceAnnotationTest {
 			return "foo";
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
-	private static RestClient ra = RestClient.create().mockHttpConnection(a).build();
+	private static MockRest a = MockRest.build(A.class, null);
 
 	@RemoteResource
 	public static interface A01a {
@@ -64,7 +64,7 @@ public class RemoteResourceAnnotationTest {
 
 	@Test
 	public void a01_noPath() throws Exception {
-		A01a t = ra.getRemoteResource(A01a.class);
+		A01a t = MockRemoteResource.build(A01a.class, A.class, null);
 		assertEquals("foo", t.a01());
 		assertEquals("foo", t.a01a());
 		assertEquals("foo", t.a01b());
@@ -82,7 +82,7 @@ public class RemoteResourceAnnotationTest {
 
 	@Test
 	public void a02a_normalPath() throws Exception {
-		A02a t = ra.getRemoteResource(A02a.class);
+		A02a t = MockRemoteResource.build(A02a.class, A.class, null);
 		assertEquals("foo", t.a02());
 		assertEquals("foo", t.a02a());
 		assertEquals("foo", t.a02b());
@@ -100,7 +100,7 @@ public class RemoteResourceAnnotationTest {
 
 	@Test
 	public void a02b_normalPathWithSlashes() throws Exception {
-		A02b t = ra.getRemoteResource(A02b.class);
+		A02b t = MockRemoteResource.build(A02b.class, A.class, null);
 		assertEquals("foo", t.a02());
 		assertEquals("foo", t.a02a());
 		assertEquals("foo", t.a02b());
@@ -138,7 +138,7 @@ public class RemoteResourceAnnotationTest {
 
 	@Test
 	public void a03a_normalPath() throws Exception {
-		A03a t = ra.getRemoteResource(A03a.class);
+		A03a t = MockRemoteResource.build(A03a.class, A.class, null);
 		assertEquals("foo", t.a03());
 		assertEquals("foo", t.a03a());
 		assertEquals("foo", t.a03b());
@@ -156,7 +156,7 @@ public class RemoteResourceAnnotationTest {
 
 	@Test
 	public void a03b_normalPathWithSlashes() throws Exception {
-		A03b t = ra.getRemoteResource(A03b.class);
+		A03b t = MockRemoteResource.build(A03b.class, A.class, null);
 		assertEquals("foo", t.a03());
 		assertEquals("foo", t.a03a());
 		assertEquals("foo", t.a03b());
@@ -224,7 +224,7 @@ public class RemoteResourceAnnotationTest {
 			return "foo";
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
+	private static MockRest b = MockRest.build(B.class, null);
 	private static RestClient rb = RestClient.create().mockHttpConnection(b).rootUrl("http://localhost/B").build();
 
 	@RemoteResource
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RequestAnnotationTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RequestAnnotationTest.java
index aebed4f..3d83abe 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RequestAnnotationTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/RequestAnnotationTest.java
@@ -24,8 +24,7 @@ import org.apache.juneau.http.annotation.Path;
 import org.apache.juneau.http.annotation.Query;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.client.*;
-import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.apache.juneau.rest.testutils.*;
 import org.junit.*;
 import org.junit.runners.*;
@@ -53,8 +52,6 @@ public class RequestAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
-
 	@Request
 	public static class ARequest {
 		@Body
@@ -80,7 +77,7 @@ public class RequestAnnotationTest {
 		@RemoteMethod(path="/{x}") String post(ARequest req);
 	}
 
-	private static AR ar = RestClient.create().mockHttpConnection(a).build().getRemoteResource(AR.class);
+	private static AR ar = MockRemoteResource.build(AR.class, A.class, null);
 
 	@Test
 	public void a01_basic() throws Exception {
@@ -107,7 +104,6 @@ public class RequestAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
 
 	@Request
 	public abstract static class BRequest {
@@ -145,7 +141,7 @@ public class RequestAnnotationTest {
 		@RemoteMethod(path="/{x}") String post(BRequest req);
 	}
 
-	private static BR br = RestClient.create().mockHttpConnection(b).build().getRemoteResource(BR.class);
+	private static BR br = MockRemoteResource.build(BR.class, B.class, null);
 
 	@Test
 	public void b01_annotationOnParent() throws Exception {
@@ -172,7 +168,6 @@ public class RequestAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
 
 	@Request
 	public interface CRequest {
@@ -210,7 +205,7 @@ public class RequestAnnotationTest {
 		@RemoteMethod(path="/{x}") String post(CRequest req);
 	}
 
-	private static CR cr = RestClient.create().mockHttpConnection(c).build().getRemoteResource(CR.class);
+	private static CR cr = MockRemoteResource.build(CR.class, C.class, null);
 
 	@Test
 	public void c01_annotationOnInterface() throws Exception {
@@ -237,7 +232,6 @@ public class RequestAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest d = MockRest.create(D.class);
 
 	public static class DRequest {
 		@Body
@@ -263,7 +257,7 @@ public class RequestAnnotationTest {
 		@RemoteMethod(path="/{x}") String post(@Request DRequest req);
 	}
 
-	private static DR dr = RestClient.create().mockHttpConnection(d).build().getRemoteResource(DR.class);
+	private static DR dr = MockRemoteResource.build(DR.class, D.class, null);
 
 	@Test
 	public void d01_annotationOnParameter() throws Exception {
@@ -290,7 +284,6 @@ public class RequestAnnotationTest {
 			return m.toString();
 		}
 	}
-	private static MockRest e = MockRest.create(E.class);
 
 	@Request(partSerializer=XPartSerializer.class)
 	public static class ERequest {
@@ -317,7 +310,7 @@ public class RequestAnnotationTest {
 		@RemoteMethod(path="/{x}") String post(ERequest req);
 	}
 
-	private static ER er = RestClient.create().mockHttpConnection(e).build().getRemoteResource(ER.class);
+	private static ER er = MockRemoteResource.build(ER.class, E.class, null);
 
 	@Test
 	public void e01_partSerializer() throws Exception {
diff --git a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/ResponseAnnotationTest.java b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/ResponseAnnotationTest.java
index 40c12ff..61b6dff 100644
--- a/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/ResponseAnnotationTest.java
+++ b/juneau-rest/juneau-rest-client/src/test/java/org/apache/juneau/rest/client/remote/ResponseAnnotationTest.java
@@ -21,8 +21,7 @@ import org.apache.juneau.http.annotation.Response;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.client.*;
-import org.apache.juneau.rest.mock.*;
+import org.apache.juneau.rest.client.mock.*;
 import org.junit.*;
 import org.junit.runners.*;
 
@@ -56,7 +55,6 @@ public class ResponseAnnotationTest {
 			return "foo";
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
 
 	@Response
 	public interface AResponse {
@@ -76,7 +74,7 @@ public class ResponseAnnotationTest {
 		@RemoteMethod AResponse get();
 	}
 
-	private static AR ar = RestClient.create().mockHttpConnection(a).build().getRemoteResource(AR.class);
+	private static AR ar = MockRemoteResource.build(AR.class, A.class, null);
 
 	@Test
 	public void a01_basic() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 30cd36c..b758b76 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -3192,7 +3192,7 @@ public final class RestContext extends BeanContext {
 					msgs.addSearchPath(mbl[i] != null ? mbl[i].baseClass : resourceClass, mbl[i].bundlePath);
 			}
 
-			fullPath = (builder.parentContext == null ? "" : (builder.parentContext.fullPath + '/')) + builder.path;
+			fullPath = (builder.parentContext == null ? "" : (builder.parentContext.fullPath + '/')) + (builder.path == null ? "_" : builder.path);
 
 			this.childResources = Collections.synchronizedMap(new LinkedHashMap<String,RestContext>());  // Not unmodifiable on purpose so that children can be replaced.
 
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockRest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockRest.java
index 58ea9c0..698caba 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockRest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockRest.java
@@ -12,10 +12,13 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.rest.mock;
 
+import java.io.*;
 import java.util.*;
 import java.util.concurrent.*;
 
+import org.apache.juneau.marshall.*;
 import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.util.*;
 import org.apache.juneau.utils.*;
 
 /**
@@ -56,54 +59,356 @@ import org.apache.juneau.utils.*;
  * </ul>
  */
 public class MockRest implements MockHttpConnection {
-	private static Map<Class<?>,RestContext> CONTEXTS = new ConcurrentHashMap<>();
+	private static Map<Class<?>,RestContext> CONTEXTS_DEBUG = new ConcurrentHashMap<>(), CONTEXTS_NORMAL = new ConcurrentHashMap<>();
 
-	private final RestContext rc;
+	private final RestContext ctx;
 
-	private MockRest(Class<?> c, boolean debug) throws Exception {
-		if (! CONTEXTS.containsKey(c)) {
-			Object r = c.newInstance();
-			RestContext rc = RestContext.create(r).logger(debug ? BasicRestLogger.class : NoOpRestLogger.class).build();
-			if (r instanceof RestServlet) {
-				((RestServlet)r).setContext(rc);
-			} else {
-				rc.postInit();
+	/** Requests headers to add to every request. */
+	protected final Map<String,Object> headers;
+
+	/** Debug mode enabled. */
+	protected final boolean debug;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param b Builder.
+	 */
+	protected MockRest(Builder b) {
+		try {
+			debug = b.debug;
+			Class<?> c = b.implClass;
+			Object o = b.implObject;
+			Map<Class<?>,RestContext> contexts = debug ? CONTEXTS_DEBUG : CONTEXTS_NORMAL;
+			if (! contexts.containsKey(c)) {
+				if (o == null)
+					o = c.newInstance();
+				RestContext rc = RestContext.create(o).logger(b.debug ? BasicRestLogger.class : NoOpRestLogger.class).build();
+				if (o instanceof RestServlet) {
+					((RestServlet)o).setContext(rc);
+				} else {
+					rc.postInit();
+				}
+				rc.postInitChildFirst();
+				contexts.put(c, rc);
 			}
-			rc.postInitChildFirst();
-			CONTEXTS.put(c, rc);
+			ctx = contexts.get(c);
+			headers = new LinkedHashMap<>(b.headers);
+		} catch (Exception e) {
+			throw new RuntimeException(e);
 		}
-		rc = CONTEXTS.get(c);
 	}
 
 	/**
-	 * Create a new mock REST interface
+	 * Creates a new builder with no REST implementation.
 	 *
-	 * @param c The REST class.
-	 * @return A new mock interface.
-	 * @throws RuntimeException
-	 * 	For testing conveniences, this method wraps all exceptions in a RuntimeException so that you can easily define mocks as reusable fields.
+	 * @return A new builder.
 	 */
-	public static MockRest create(Class<?> c) throws RuntimeException {
-		return create(c, false);
+	public static Builder create() {
+		return new Builder();
 	}
 
 	/**
-	 * Create a new mock REST interface
+	 * Creates a new builder with the specified REST implementation class.
 	 *
-	 * @param c The REST class.
-	 * @param debug
-	 * 	If <jk>true</jk>, the REST interface will use the {@link BasicRestLogger} for logging.
-	 * 	<br>Otherwise, uses {@link NoOpRestLogger}.
-	 * @return A new mock interface.
-	 * @throws RuntimeException
-	 * 	For testing conveniences, this method wraps all exceptions in a RuntimeException so that you can easily define mocks as reusable fields.
+	 * <p>
+	 * Uses Simple-JSON as the protocol by default.
+	 *
+	 * @param impl
+	 * 	The REST bean class.
+	 * 	<br>Class must have a no-arg constructor.
+	 * 	<br>Use {@link #create(Object)} for already-instantiated REST classes.
+	 * @return A new builder.
 	 */
-	public static MockRest create(Class<?> c, boolean debug) throws RuntimeException {
-		try {
-			return new MockRest(c, debug);
-		} catch (Exception e) {
-			throw new RuntimeException(e);
+	public static Builder create(Class<?> impl) {
+		return create().impl(impl);
+	}
+
+	/**
+	 * Creates a new builder with the specified REST implementation class.
+	 *
+	 * <p>
+	 * Uses Simple-JSON as the protocol by default.
+	 *
+	 * @param impl The REST bean.
+	 * @return A new builder.
+	 */
+	public static Builder create(Object impl) {
+		return create().impl(impl);
+	}
+
+	/**
+	 * Convenience method for creating a MockRest over the specified REST implementation.
+	 *
+	 * <p>
+	 * Equivalent to calling:
+	 * <p class='bpcode w800'>
+	 * 	MockRest.create(impl, SimpleJson.<jsf>DEFAULT</jsf>).build();
+	 * </p>
+	 *
+	 * @param impl The REST bean class.
+	 * @return A new {@link MockRest} object.
+	 */
+	public static MockRest build(Class<?> impl) {
+		return build(impl, SimpleJson.DEFAULT);
+	}
+
+	/**
+	 * Convenience method for creating a MockRest over the specified REST implementation.
+	 *
+	 * <p>
+	 * Equivalent to calling:
+	 * <p class='bpcode w800'>
+	 * 	MockRest.create(impl, SimpleJson.<jsf>DEFAULT</jsf>).build();
+	 * </p>
+	 *
+	 * @param impl The REST bean.
+	 * @return A new {@link MockRest} object.
+	 */
+	public static MockRest build(Object impl) {
+		return build(impl, SimpleJson.DEFAULT);
+	}
+
+	/**
+	 * Convenience method for creating a MockRest over the specified REST implementation.
+	 *
+	 * @param impl The REST bean class.
+	 * @param m
+	 * 	The marshall to use for serializing and parsing HTTP bodies.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new {@link MockRest} object.
+	 */
+	public static MockRest build(Class<?> impl, Marshall m) {
+		Builder b = create().impl(impl);
+		if (m != null)
+			b.accept(m.getParser().getPrimaryMediaType().toString()).contentType(m.getSerializer().getPrimaryMediaType().toString());
+		return b.build();
+	}
+
+	/**
+	 * Convenience method for creating a MockRest over the specified REST implementation.
+	 *
+	 * @param impl The REST bean object.
+	 * @param m
+	 * 	The marshall to use for serializing and parsing HTTP bodies.
+	 * 	<br>Can be <jk>null</jk>.
+	 * @return A new {@link MockRest} object.
+	 */
+	public static MockRest build(Object impl, Marshall m) {
+		Builder b = create().impl(impl);
+		if (m != null)
+			b.accept(m.getParser().getPrimaryMediaType().toString()).contentType(m.getSerializer().getPrimaryMediaType().toString());
+		return b.build();
+	}
+
+	/**
+	 * Returns the headers that were defined in this class.
+	 *
+	 * @return The headers that were defined in this class.  Never <jk>null</jk>.
+	 */
+	public Map<String,Object> getHeaders() {
+		return headers;
+	}
+
+	/**
+	 * Builder class.
+	 */
+	public static class Builder {
+		Class<?> implClass;
+		Object implObject;
+		boolean debug;
+		Map<String,Object> headers = new LinkedHashMap<>();
+
+		/**
+		 * Specifies the REST implementation class.
+		 *
+		 * @param value
+		 * 	The REST implementation class.
+		 * 	<br>Class must have a no-arg constructor.
+		 * @return This object (for method chaining).
+		 */
+		public Builder impl(Class<?> value) {
+			this.implClass = value;
+			return this;
+		}
+
+		/**
+		 * Specifies the REST implementation bean.
+		 *
+		 * @param value
+		 * 	The REST implementation bean.
+		 * @return This object (for method chaining).
+		 */
+		public Builder impl(Object value) {
+			if (value instanceof Class) {
+				this.implClass = (Class<?>)value;
+			} else {
+				this.implObject = value;
+				this.implClass = value.getClass();
+			}
+			return this;
+		}
+
+		/**
+		 * Enable debug mode.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder debug() {
+			this.debug = true;
+			return this;
+		}
+
+		/**
+		 * Adds a header to every request.
+		 *
+		 * @param name The header name.
+		 * @param value
+		 * 	The header value.
+		 * 	<br>Can be <jk>null</jk> (will be skipped).
+		 * @return This object (for method chaining).
+		 */
+		public Builder header(String name, Object value) {
+			this.headers.put(name, value);
+			return this;
+		}
+
+		/**
+		 * Adds the specified headers to every request.
+		 *
+		 * @param value
+		 * 	The header values.
+		 * 	<br>Can be <jk>null</jk> (existing values will be cleared).
+		 * 	<br><jk>null</jk> null map values will be ignored.
+		 * @return This object (for method chaining).
+		 */
+		public Builder headers(Map<String,Object> value) {
+			if (value != null)
+				this.headers.putAll(value);
+			else
+				this.headers.clear();
+			return this;
+		}
+
+		/**
+		 * Adds an <code>Accept</code> header to every request.
+		 *
+		 * @param value The <code>Accept/code> header value.
+		 * @return This object (for method chaining).
+		 */
+		public Builder accept(String value) {
+			return header("Accept", value);
+		}
+
+		/**
+		 * Adds a <code>Content-Type</code> header to every request.
+		 *
+		 * @param value The <code>Content-Type</code> header value.
+		 * @return This object (for method chaining).
+		 */
+		public Builder contentType(String value) {
+			return header("Content-Type", value);
+		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"application/json"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder json() {
+			return accept("application/json").contentType("application/json");
+		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"application/json+simple"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder simpleJson() {
+			return accept("application/json+simple").contentType("application/json+simple");
+		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/xml"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder xml() {
+			return accept("text/xml").contentType("text/xml");
+		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/html"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder html() {
+			return accept("text/html").contentType("text/html");
+		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/plain"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder plainText() {
+			return accept("text/plain").contentType("text/plain");
+		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"octal/msgpack"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder msgpack() {
+			return accept("octal/msgpack").contentType("octal/msgpack");
+		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/uon"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder uon() {
+			return accept("text/uon").contentType("text/uon");
+		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"application/x-www-form-urlencoded"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder urlEnc() {
+			return accept("application/x-www-form-urlencoded").contentType("application/x-www-form-urlencoded");
 		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/yaml"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder yaml() {
+			return accept("text/yaml").contentType("text/yaml");
+		}
+
+		/**
+		 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"text/openapi"</js>.
+		 *
+		 * @return This object (for method chaining).
+		 */
+		public Builder openapi() {
+			return accept("text/openapi").contentType("text/openapi");
+		}
+
+		/**
+		 * Create a new {@link MockRest} object based on the settings on this builder.
+		 *
+		 * @return A new {@link MockRest} object.
+		 */
+		public MockRest build() {
+			return new MockRest(this);
+		}
+
 	}
 
 	/**
@@ -111,13 +416,24 @@ public class MockRest implements MockHttpConnection {
 	 *
 	 * @param method The HTTP method
 	 * @param path The URI path.
-	 * @param body The body of the request.
+	 * @param headers Optional headers to include in the request.
+	 * @param body
+	 * 	The body of the request.
+	 * 	<br>Can be any of the following data types:
+	 * 	<ul>
+	 * 		<li><code><jk>byte</jk>[]</code>
+	 * 		<li>{@link Reader}
+	 * 		<li>{@link InputStream}
+	 * 		<li>{@link CharSequence}
+	 * 	</ul>
+	 * 	Any other types are converted to a string using the <code>toString()</code> method.
 	 * @return A new servlet request.
 	 * @throws Exception
 	 */
 	@Override /* MockHttpConnection */
-	public MockServletRequest request(String method, String path, Object body) throws Exception {
-		return MockServletRequest.create(method, path).body(body).restContext(rc);
+	public MockServletRequest request(String method, String path, Map<String,Object> headers, Object body) throws Exception {
+		String p = RestUtils.trimContextPath(ctx.getPath(), path);
+		return MockServletRequest.create(method, p).body(body).headers(this.headers).headers(headers).debug(debug).restContext(ctx);
 	}
 
 	/**
@@ -129,7 +445,20 @@ public class MockRest implements MockHttpConnection {
 	 * @throws Exception
 	 */
 	public MockServletRequest request(String method, String path) throws Exception {
-		return request(method, path, null);
+		return request(method, path, null, null);
+	}
+
+	/**
+	 * Performs a REST request against the REST interface.
+	 *
+	 * @param method The HTTP method
+	 * @param headers Optional headers to include in the request.
+	 * @param path The URI path.
+	 * @return A new servlet request.
+	 * @throws Exception
+	 */
+	public MockServletRequest request(String method, Map<String,Object> headers, String path) throws Exception {
+		return request(method, path, headers, null);
 	}
 
 	/**
@@ -140,7 +469,7 @@ public class MockRest implements MockHttpConnection {
 	 * @throws Exception
 	 */
 	public MockServletRequest get(String path) throws Exception {
-		return request("GET", path, null);
+		return request("GET", path, null, null);
 	}
 
 	/**
@@ -152,7 +481,7 @@ public class MockRest implements MockHttpConnection {
 	 * @throws Exception
 	 */
 	public MockServletRequest put(String path, Object body) throws Exception {
-		return request("PUT", path, body);
+		return request("PUT", path, null, body);
 	}
 
 	/**
@@ -164,7 +493,7 @@ public class MockRest implements MockHttpConnection {
 	 * @throws Exception
 	 */
 	public MockServletRequest post(String path, Object body) throws Exception {
-		return request("POST", path, body);
+		return request("POST", path, null, body);
 	}
 
 	/**
@@ -175,7 +504,7 @@ public class MockRest implements MockHttpConnection {
 	 * @throws Exception
 	 */
 	public MockServletRequest delete(String path) throws Exception {
-		return request("DELETE", path, null);
+		return request("DELETE", path, null, null);
 	}
 
 	/**
@@ -186,6 +515,18 @@ public class MockRest implements MockHttpConnection {
 	 * @throws Exception
 	 */
 	public MockServletRequest options(String path) throws Exception {
-		return request("OPTIONS", path, null);
+		return request("OPTIONS", path, null, null);
+	}
+
+	/**
+	 * Perform a PATCH request.
+	 *
+	 * @param path The URI path.
+	 * @param body The body of the request.
+	 * @return A new servlet request.
+	 * @throws Exception
+	 */
+	public MockServletRequest patch(String path, Object body) throws Exception {
+		return request("PATCH", path, null, body);
 	}
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
index a41973b..5a9b1fd 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
@@ -114,12 +114,41 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	}
 
 	/**
+	 * Specifies the <code>Accept</code> header value.
+	 *
+	 * @param value The <code>Accept</code> header value.
+	 * @return This object (for method chaining).
+	 */
+	public MockServletRequest accept(String value) {
+		return header("Accept", value);
+	}
+
+	/**
+	 * Specifies the <code>Content-Type</code> header value.
+	 *
+	 * @param value The <code>Content-Type</code> header value.
+	 * @return This object (for method chaining).
+	 */
+	public MockServletRequest contentType(String value) {
+		return header("Content-Type", value);
+	}
+
+	/**
 	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"application/json"</js>.
 	 *
 	 * @return This object (for method chaining).
 	 */
 	public MockServletRequest json() {
-		return header("Accept", "application/json").header("Content-Type", "application/json");
+		return accept("application/json").contentType("application/json");
+	}
+
+	/**
+	 * Convenience method for setting <code>Accept</code> and <code>Content-Type</code> headers to <js>"application/json+simple"</js>.
+	 *
+	 * @return This object (for method chaining).
+	 */
+	public MockServletRequest simpleJson() {
+		return accept("application/json+simple").contentType("application/json+simple");
 	}
 
 	/**
@@ -128,7 +157,7 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	 * @return This object (for method chaining).
 	 */
 	public MockServletRequest xml() {
-		return header("Accept", "text/xml").header("Content-Type", "text/xml");
+		return accept("text/xml").contentType("text/xml");
 	}
 
 	/**
@@ -137,7 +166,7 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	 * @return This object (for method chaining).
 	 */
 	public MockServletRequest html() {
-		return header("Accept", "text/html").header("Content-Type", "text/html");
+		return accept("text/html").contentType("text/html");
 	}
 
 	/**
@@ -146,7 +175,7 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	 * @return This object (for method chaining).
 	 */
 	public MockServletRequest plainText() {
-		return header("Accept", "text/plain").header("Content-Type", "text/plain");
+		return accept("text/plain").contentType("text/plain");
 	}
 
 	/**
@@ -155,7 +184,7 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	 * @return This object (for method chaining).
 	 */
 	public MockServletRequest msgpack() {
-		return header("Accept", "octal/msgpack").header("Content-Type", "octal/msgpack");
+		return accept("octal/msgpack").contentType("octal/msgpack");
 	}
 
 	/**
@@ -164,7 +193,7 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	 * @return This object (for method chaining).
 	 */
 	public MockServletRequest uon() {
-		return header("Accept", "text/uon").header("Content-Type", "text/uon");
+		return accept("text/uon").contentType("text/uon");
 	}
 
 	/**
@@ -173,7 +202,7 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	 * @return This object (for method chaining).
 	 */
 	public MockServletRequest urlEnc() {
-		return header("Accept", "application/x-www-form-urlencoded").header("Content-Type", "application/x-www-form-urlencoded");
+		return accept("application/x-www-form-urlencoded").contentType("application/x-www-form-urlencoded");
 	}
 
 	/**
@@ -182,7 +211,7 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	 * @return This object (for method chaining).
 	 */
 	public MockServletRequest yaml() {
-		return header("Accept", "text/yaml").header("Content-Type", "text/yaml");
+		return accept("text/yaml").contentType("text/yaml");
 	}
 
 	/**
@@ -234,7 +263,12 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 		sb.append("\n=== HTTP Call =================================================================");
 
 		sb.append("\n=== REQUEST ===");
-		sb.append("\nTODO");
+		sb.append("\n---request headers---");
+		for (Map.Entry<String,String[]> h : req.getHeaders().entrySet())
+			for (String h2 : h.getValue())
+				sb.append("\n").append(h.getKey()).append(": ").append(h2);
+		sb.append("\n---request entity---");
+		sb.append(body == null ? "NONE" : new String(body));
 		sb.append("\n=== RESPONSE ===");
 		sb.append("\nStatus: ").append(res.getStatus());
 		sb.append("\n---response headers---");
@@ -798,6 +832,15 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 		return Collections.enumeration(Arrays.asList(s == null ? new String[0] : s));
 	}
 
+	/**
+	 * Returns the headers defined on this request.
+	 *
+	 * @return The headers defined on this request.  Never <jk>null</jk>.
+	 */
+	public Map<String,String[]> getHeaders() {
+		return headerMap;
+	}
+
 	@Override /* HttpServletRequest */
 	public Enumeration<String> getHeaderNames() {
 		return Collections.enumeration(headerMap.keySet());
@@ -960,6 +1003,19 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	/**
 	 * Fluent setter.
 	 *
+	 * @param headers Headers to add to this request.
+	 * @return This object (for method chaining).
+	 */
+	public MockServletRequest headers(Map<String,Object> headers) {
+		if (headers != null)
+			for (Map.Entry<String,Object> e : headers.entrySet())
+				header(e.getKey(), e.getValue());
+		return this;
+	}
+
+	/**
+	 * Fluent setter.
+	 *
 	 * @param name Header name.
 	 * @param value
 	 * 	Header value.
@@ -968,7 +1024,10 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	 */
 	@Override /* MockHttpRequest */
 	public MockServletRequest header(String name, Object value) {
-		this.headerMap.put(name, new String[] {asString(value)});
+		if (value == null)
+			headerMap.remove(name);
+		else
+			headerMap.put(name, new String[] {asString(value)});
 		return this;
 	}
 
@@ -996,6 +1055,7 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 	 * 		<li>{@link InputStream}
 	 * 		<li>{@link CharSequence}
 	 * 	</ul>
+	 * 	Any other types are converted to a string using the <code>toString()</code> method.
 	 * @return This object (for method chaining).
 	 */
 	@Override /* MockHttpRequest */
@@ -1003,12 +1063,14 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 		try {
 			if (value instanceof byte[])
 				this.body = (byte[])value;
-			if (value instanceof Reader)
+			else if (value instanceof Reader)
 				this.body = IOUtils.read((Reader)value).getBytes();
-			if (value instanceof InputStream)
+			else if (value instanceof InputStream)
 				this.body = IOUtils.readBytes((InputStream)value, 1024);
-			if (value instanceof CharSequence)
+			else if (value instanceof CharSequence)
 				this.body = ((CharSequence)value).toString().getBytes();
+			else if (value != null)
+				this.body = value.toString().getBytes();
 		} catch (IOException e) {
 			throw new RuntimeException(e);
 		}
@@ -1363,4 +1425,18 @@ public class MockServletRequest implements HttpServletRequest, MockHttpRequest {
 		this.debug = true;
 		return this;
 	}
+
+	/**
+	 * Enabled debug mode on this request.
+	 *
+	 * <p>
+	 * Causes information about the request execution to be sent to STDERR.
+	 *
+	 * @param value The enable flag value.
+	 * @return This object (for method chaining).
+	 */
+	public MockServletRequest debug(boolean value) {
+		this.debug = value;
+		return this;
+	}
 }
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/RestUtils.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/RestUtils.java
index fde2eff..fc6d358 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/RestUtils.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/RestUtils.java
@@ -412,4 +412,31 @@ public final class RestUtils {
 		}
 		return l.toArray(new Object[l.size()]);
 	}
+
+	/**
+	 * If the specified path-info starts with the specified context path, trims the context path from the path info.
+	 *
+	 * @param contextPath The context path.
+	 * @param path The URL path.
+	 * @return The path following the context path, or the original path.
+	 */
+	public static String trimContextPath(String contextPath, String path) {
+		if (path == null)
+			return null;
+		if (path.length() == 0 || path.equals("/") || contextPath.length() == 0 || contextPath.equals("/"))
+			return path;
+		String op = path;
+		if (path.charAt(0) == '/')
+			path = path.substring(1);
+		if (contextPath.charAt(0) == '/')
+			contextPath = contextPath.substring(1);
+		if (path.startsWith(contextPath)) {
+			if (path.length() == contextPath.length())
+				return "/";
+			path = path.substring(contextPath.length());
+			if (path.isEmpty() || path.charAt(0) == '/')
+				return path;
+		}
+		return op;
+	}
 }
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/jueau/rest/helper/ReaderResourceTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/jueau/rest/helper/ReaderResourceTest.java
index 1f9e34e..2db59fc 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/jueau/rest/helper/ReaderResourceTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/jueau/rest/helper/ReaderResourceTest.java
@@ -71,7 +71,7 @@ public class ReaderResourceTest {
 		}
 	}
 
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01_basic() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/jueau/rest/helper/StreamResourceTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/jueau/rest/helper/StreamResourceTest.java
index fab3b33..38ad4af 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/jueau/rest/helper/StreamResourceTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/jueau/rest/helper/StreamResourceTest.java
@@ -70,7 +70,7 @@ public class StreamResourceTest {
 		}
 	}
 
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01_basic() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
index f7a2c52..c028638 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BasicRestInfoProviderTest.java
@@ -2341,7 +2341,7 @@ public class BasicRestInfoProviderTest {
 		}
 	}
 
-	static MockRest p = MockRest.create(P.class);
+	static MockRest p = MockRest.build(P.class);
 
 	@Test
 	public void p01_bodyWithReadOnlyProperty() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BeanContextPropertiesTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BeanContextPropertiesTest.java
index dfc07c7..44b7bc1 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BeanContextPropertiesTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/BeanContextPropertiesTest.java
@@ -46,7 +46,7 @@ public class BeanContextPropertiesTest  {
 			return "d1="+df.swap(session, d1)+",d2="+df.swap(session, d2)+",d3="+df.swap(session, d3)+"";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_testClassTransforms() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/NlsTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/NlsTest.java
index d51806d..c18aa55 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/NlsTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/NlsTest.java
@@ -48,7 +48,7 @@ public class NlsTest {
 			return null;
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	public static class A01 extends WriterSerializer {
 		public A01(PropertyStore ps) {
@@ -87,7 +87,7 @@ public class NlsTest {
 			return req.getSwagger();
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_optionsPageWithoutNls() throws Exception {
@@ -106,7 +106,7 @@ public class NlsTest {
 			return req.getMessage("bad", 1, 2, 3);
 		}
 	}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class, null);
 
 	@Test
 	public void c01_missingResourceBundle() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/PathsTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/PathsTest.java
index ccf6e1c..69342e4 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/PathsTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/PathsTest.java
@@ -56,7 +56,7 @@ public class PathsTest {
 			return getPaths(req).append("pathRemainder2", r).append("method",1);
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01() throws Exception {
@@ -204,7 +204,7 @@ public class PathsTest {
 			return getPaths(req).append("pathRemainder2", r).append("method",2);
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01() throws Exception {
@@ -356,7 +356,7 @@ public class PathsTest {
 			return getPaths(req).append("pathRemainder2", r).append("method",3);
 		}
 	}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class, null);
 
 	@Test
 	public void c01() throws Exception {
@@ -508,7 +508,7 @@ public class PathsTest {
 			return getPaths(req).append("pathRemainder2", r).append("method",4);
 		}
 	}
-	static MockRest d = MockRest.create(D.class);
+	static MockRest d = MockRest.build(D.class, null);
 
 	@Test
 	public void d01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/RestParamsTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/RestParamsTest.java
index 2c0d651..cecf860 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/RestParamsTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/RestParamsTest.java
@@ -125,7 +125,7 @@ public class RestParamsTest {
 			return t != null;
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_ResourceBundle() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/StatusCodesTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/StatusCodesTest.java
index 842ba3a..cc76593 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/StatusCodesTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/StatusCodesTest.java
@@ -43,7 +43,7 @@ public class StatusCodesTest {
 			return new StringReader(b);
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
+	private static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01a_OK() throws Exception {
@@ -108,7 +108,7 @@ public class StatusCodesTest {
 			return "OK";
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
+	private static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01a_nonExistentBeanProperties() throws Exception {
@@ -202,7 +202,7 @@ public class StatusCodesTest {
 			return "OK";
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
+	private static MockRest c = MockRest.build(C.class);
 
 	@Test
 	public void c01_badPath() throws Exception {
@@ -237,7 +237,7 @@ public class StatusCodesTest {
 			}
 		}
 	}
-	private static MockRest d = MockRest.create(D.class);
+	private static MockRest d = MockRest.build(D.class);
 
 	@Test
 	public void d01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/ThreadLocalObjectsTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/ThreadLocalObjectsTest.java
index 462060b..bf66e81 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/ThreadLocalObjectsTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/ThreadLocalObjectsTest.java
@@ -44,7 +44,7 @@ public class ThreadLocalObjectsTest {
 			assertNull(getResponse());
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -70,7 +70,7 @@ public class ThreadLocalObjectsTest {
 			assertNull(getResponse());
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocAsideTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocAsideTest.java
index 9ef8d0b..4656c75 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocAsideTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocAsideTest.java
@@ -51,7 +51,7 @@ public class HtmlDocAsideTest {
 			return "OK";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -101,7 +101,7 @@ public class HtmlDocAsideTest {
 			return "OK";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocFooterTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocFooterTest.java
index 0e48866..bd58daf 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocFooterTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocFooterTest.java
@@ -51,7 +51,7 @@ public class HtmlDocFooterTest {
 			return "OK";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -101,7 +101,7 @@ public class HtmlDocFooterTest {
 			return "OK";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocHeaderTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocHeaderTest.java
index 6a8abf0..a3beaf8 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocHeaderTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocHeaderTest.java
@@ -51,7 +51,7 @@ public class HtmlDocHeaderTest {
 			return "OK";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -101,7 +101,7 @@ public class HtmlDocHeaderTest {
 			return "OK";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavTest.java
index 0852a46..63ae137 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavTest.java
@@ -51,7 +51,7 @@ public class HtmlDocNavTest {
 			return "OK";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -101,7 +101,7 @@ public class HtmlDocNavTest {
 			return "OK";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavlinksTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavlinksTest.java
index 37dc501..36d8df6 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavlinksTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocNavlinksTest.java
@@ -76,7 +76,7 @@ public class HtmlDocNavlinksTest {
 			return "OK";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -174,7 +174,7 @@ public class HtmlDocNavlinksTest {
 			return "OK";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 
 	@Test
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocScriptTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocScriptTest.java
index 67cdfa2..7922f1a 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocScriptTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocScriptTest.java
@@ -51,7 +51,7 @@ public class HtmlDocScriptTest {
 			return "OK";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -101,7 +101,7 @@ public class HtmlDocScriptTest {
 			return "OK";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocStyleTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocStyleTest.java
index bef342b..df8826d 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocStyleTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/HtmlDocStyleTest.java
@@ -51,7 +51,7 @@ public class HtmlDocStyleTest {
 			return "OK";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -101,7 +101,7 @@ public class HtmlDocStyleTest {
 			return "OK";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java
index 46deac4..64a7655 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseHeaderAnnotationTest.java
@@ -55,7 +55,7 @@ public class ResponseHeaderAnnotationTest {
 		public String toString() {return "foo";}
 	}
 
-	static MockRest a = MockRest.create(A.class,true);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01_valueOnParameterPojo() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java
index 1a801c7..9d76202 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/ResponseStatusAnnotationTest.java
@@ -37,7 +37,7 @@ public class ResponseStatusAnnotationTest {
 		}
 	}
 
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodBpiTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodBpiTest.java
index 1f14587..4039a32 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodBpiTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodBpiTest.java
@@ -45,7 +45,7 @@ public class RestMethodBpiTest {
 			return new MyBeanA().init();
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -92,7 +92,7 @@ public class RestMethodBpiTest {
 			return new MyBeanA().init();
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01() throws Exception {
@@ -139,7 +139,7 @@ public class RestMethodBpiTest {
 			return new MyBeanB().init();
 		}
 	}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class);
 
 	@Test
 	public void c01() throws Exception {
@@ -186,7 +186,7 @@ public class RestMethodBpiTest {
 			return new MyBeanB().init();
 		}
 	}
-	static MockRest d = MockRest.create(D.class);
+	static MockRest d = MockRest.build(D.class);
 
 	@Test
 	public void d01() throws Exception {
@@ -225,7 +225,7 @@ public class RestMethodBpiTest {
 			return new MyBeanA().init();
 		}
 	}
-	static MockRest e = MockRest.create(E.class);
+	static MockRest e = MockRest.build(E.class);
 
 	@Test
 	public void e01() throws Exception {
@@ -248,7 +248,7 @@ public class RestMethodBpiTest {
 			return new MyBeanA().init();
 		}
 	}
-	static MockRest f = MockRest.create(F.class);
+	static MockRest f = MockRest.build(F.class);
 
 	@Test
 	public void f01() throws Exception {
@@ -277,7 +277,7 @@ public class RestMethodBpiTest {
 			return new MyBeanA().init();
 		}
 	}
-	static MockRest g = MockRest.create(G.class);
+	static MockRest g = MockRest.build(G.class);
 
 	@Test
 	public void g01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodGuardsTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodGuardsTest.java
index 35f9c6f..52a452d 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodGuardsTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodGuardsTest.java
@@ -51,7 +51,7 @@ public class RestMethodGuardsTest {
 			}
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_overlappingOneGuard() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodMatchersTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodMatchersTest.java
index 89c4554..8a1efef 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodMatchersTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodMatchersTest.java
@@ -66,7 +66,7 @@ public class RestMethodMatchersTest {
 			}
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java
index 82de0c6..7a676e1 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestMethodPathTest.java
@@ -64,7 +64,7 @@ public class RestMethodPathTest {
 			return "h";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_overlappingPaths() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceMessagesTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceMessagesTest.java
index 5406485..c184b05 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceMessagesTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceMessagesTest.java
@@ -48,7 +48,7 @@ public class RestResourceMessagesTest {
 			return convertToMap(rb);
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01() throws Exception {
@@ -62,7 +62,7 @@ public class RestResourceMessagesTest {
 
 	@RestResource(messages="RestResourceMessagesTest2")
 	public static class B extends A {}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourcePathTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourcePathTest.java
index 1794941..8268242 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourcePathTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourcePathTest.java
@@ -53,7 +53,7 @@ public class RestResourcePathTest {
 	@RestResource(path="/p2")
 	public static class A02 extends A02a {}
 
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_nestedChildren() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourcePropertiesTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourcePropertiesTest.java
index 318ebb3..a85d8ab 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourcePropertiesTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourcePropertiesTest.java
@@ -82,7 +82,7 @@ public class RestResourcePropertiesTest {
 			}
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceSerializersTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceSerializersTest.java
index 93c65df..ee08149 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceSerializersTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceSerializersTest.java
@@ -118,7 +118,7 @@ public class RestResourceSerializersTest {
 			return "test406";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01_serializerOnClass() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceStaticFilesTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceStaticFilesTest.java
index 76d7f21..95aa27e 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceStaticFilesTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation/RestResourceStaticFilesTest.java
@@ -34,7 +34,7 @@ public class RestResourceStaticFilesTest {
 			return null;
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01() throws Exception {
@@ -58,7 +58,7 @@ public class RestResourceStaticFilesTest {
 			return null;
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/AnnotationInheritanceTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/AnnotationInheritanceTest.java
index 6c0b5c5..17ecb93 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/AnnotationInheritanceTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/AnnotationInheritanceTest.java
@@ -64,7 +64,7 @@ public class AnnotationInheritanceTest {
 		}
 	}
 
-	private static MockRest a = MockRest.create(A.class);
+	private static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01_inherited_Body() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/BodyAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/BodyAnnotationTest.java
index 40514ab..e1cbb2c 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/BodyAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/BodyAnnotationTest.java
@@ -125,7 +125,7 @@ public class BodyAnnotationTest {
 			@Override public String toString() { return s; }
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
+	private static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01a_onParameter_String() throws Exception {
@@ -315,7 +315,7 @@ public class BodyAnnotationTest {
 			@Override public String toString() { return s; }
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
+	private static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01a_onPojo_StringTransform() throws Exception {
@@ -534,7 +534,7 @@ public class BodyAnnotationTest {
 			@Override public String toString() { return s; }
 		}
 	}
-	private static MockRest d = MockRest.create(D.class);
+	private static MockRest d = MockRest.build(D.class, null);
 
 	@Test
 	public void d01a_noMediaTypes_String() throws Exception {
@@ -624,7 +624,7 @@ public class BodyAnnotationTest {
 			return c;
 		}
 	}
-	private static MockRest e = MockRest.create(E.class);
+	private static MockRest e = MockRest.build(E.class);
 
 	@Test
 	public void e01_complexPojos_B_body() throws Exception {
@@ -665,7 +665,7 @@ public class BodyAnnotationTest {
 			public int p2;
 		}
 	}
-	static MockRest f = MockRest.create(F.class);
+	static MockRest f = MockRest.build(F.class);
 
 	@Test
 	public void f01_formPostAsContent() throws Exception {
@@ -688,7 +688,7 @@ public class BodyAnnotationTest {
 			return content;
 		}
 	}
-	static MockRest g = MockRest.create(G.class);
+	static MockRest g = MockRest.build(G.class);
 
 	@Test
 	public void g01() throws Exception {
@@ -734,7 +734,7 @@ public class BodyAnnotationTest {
 			return content;
 		}
 	}
-	static MockRest h = MockRest.create(H.class);
+	static MockRest h = MockRest.build(H.class);
 
 	@Test
 	public void h01() throws Exception {
@@ -773,7 +773,7 @@ public class BodyAnnotationTest {
 			return content;
 		}
 	}
-	static MockRest i = MockRest.create(I.class);
+	static MockRest i = MockRest.build(I.class);
 
 	@Test
 	public void i01() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/FormDataAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/FormDataAnnotationTest.java
index 83cbddf..9189877 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/FormDataAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/FormDataAnnotationTest.java
@@ -47,7 +47,7 @@ public class FormDataAnnotationTest {
 			return "p1=["+p1+","+req.getFormData().getString("p1")+","+f.get("p1", String.class)+"],p2=["+p2+","+req.getFormData().getString("p2")+","+f.get("p2", int.class)+"]";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01() throws Exception {
@@ -82,7 +82,7 @@ public class FormDataAnnotationTest {
 			return "p1=["+p1+","+req.getFormData().getString("p1")+","+f.get("p1", String.class)+"]";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01() throws Exception {
@@ -130,7 +130,7 @@ public class FormDataAnnotationTest {
 				.append("f3", f3);
 		}
 	}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class, null);
 
 	@Test
 	public void c01_defaultFormData() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/HasFormDataAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/HasFormDataAnnotationTest.java
index fed148e..54df9aa 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/HasFormDataAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/HasFormDataAnnotationTest.java
@@ -39,7 +39,7 @@ public class HasFormDataAnnotationTest {
 		}
 
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_post() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/HasQueryAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/HasQueryAnnotationTest.java
index b82ae31..497d2d2 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/HasQueryAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/HasQueryAnnotationTest.java
@@ -45,7 +45,7 @@ public class HasQueryAnnotationTest {
 			return "p1=["+p1+","+q.containsKey("p1")+"],p2=["+p2+","+q.containsKey("p2")+"]";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_get() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
index d659603..f9bea60 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathAnnotationTest.java
@@ -61,7 +61,7 @@ public class PathAnnotationTest {
 			return "GET /a "+foo+","+bar+",r="+remainder;
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a00_nonExistentPath() throws Exception {
@@ -137,7 +137,7 @@ public class PathAnnotationTest {
 			return String.valueOf(x);
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_int() throws Exception {
@@ -219,7 +219,7 @@ public class PathAnnotationTest {
 			return String.valueOf(x);
 		}
 	}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class, null);
 
 	@Test
 	public void c01_Integer() throws Exception {
@@ -274,7 +274,7 @@ public class PathAnnotationTest {
 			return uuid;
 		}
 	}
-	static MockRest d = MockRest.create(D.class);
+	static MockRest d = MockRest.build(D.class, null);
 
 	@Test
 	public void d01_uuid() throws Exception {
@@ -309,7 +309,7 @@ public class PathAnnotationTest {
 			return new ObjectMap().append("m","numbers3").append("0", foo).append("1", bar);
 		}
 	}
-	static MockRest e = MockRest.create(E.class);
+	static MockRest e = MockRest.build(E.class, null);
 
 	@Test
 	public void e01_normal1() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathRemainderAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathRemainderAnnotationTest.java
index 8030718..b3887f9 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathRemainderAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/PathRemainderAnnotationTest.java
@@ -38,7 +38,7 @@ public class PathRemainderAnnotationTest {
 			return remainder;
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_withoutRemainder() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/QueryAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/QueryAnnotationTest.java
index b778a9a..4da3c27 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/QueryAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/QueryAnnotationTest.java
@@ -53,7 +53,7 @@ public class QueryAnnotationTest {
 			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"],p2=["+p2+","+q.getString("p2")+","+q.get("p2", int.class)+"]";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_get() throws Exception {
@@ -113,7 +113,7 @@ public class QueryAnnotationTest {
 			return "p1=["+p1+","+req.getQuery().getString("p1")+","+q.get("p1", String.class)+"]";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_get1() throws Exception {
@@ -173,7 +173,7 @@ public class QueryAnnotationTest {
 			return x;
 		}
 	}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class);
 
 	@Test
 	public void c01_StringArray() throws Exception {
@@ -241,7 +241,7 @@ public class QueryAnnotationTest {
 				.append("f3", f3);
 		}
 	}
-	static MockRest d = MockRest.create(D.class);
+	static MockRest d = MockRest.build(D.class, null);
 
 	@Test
 	public void d01_defaultQuery() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
index e51a05d..7cd9519 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/ResponseAnnotationTest.java
@@ -70,7 +70,7 @@ public class ResponseAnnotationTest {
 		public String toString() {return "foo";}
 	}
 
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_codeOnClass() throws Exception {
@@ -123,7 +123,7 @@ public class ResponseAnnotationTest {
 		public String toString() {return "foo";}
 	}
 
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_useOnMethod() throws Exception {
@@ -214,7 +214,7 @@ public class ResponseAnnotationTest {
 		}
 	}
 
-	static MockRest d = MockRest.create(D.class);
+	static MockRest d = MockRest.build(D.class, null);
 
 	@Test
 	public void d01_useOnMethod() throws Exception {
@@ -285,7 +285,7 @@ public class ResponseAnnotationTest {
 		public String toString() {return "foo";}
 	}
 
-	static MockRest e = MockRest.create(E.class);
+	static MockRest e = MockRest.build(E.class, null);
 
 	@Test
 	public void e01_basic_onParameter() throws Exception {
@@ -337,7 +337,7 @@ public class ResponseAnnotationTest {
 		}
 	}
 
-	static MockRest f = MockRest.create(F.class);
+	static MockRest f = MockRest.build(F.class, null);
 	static Swagger sf = getSwagger(F.class);
 
 	@Test
@@ -410,7 +410,7 @@ public class ResponseAnnotationTest {
 		}
 	}
 
-	static MockRest g = MockRest.create(G.class);
+	static MockRest g = MockRest.build(G.class);
 	static Swagger sg = getSwagger(G.class);
 
 	@Test
@@ -467,7 +467,7 @@ public class ResponseAnnotationTest {
 			return body;
 		}
 	}
-	static MockRest j = MockRest.create(J.class);
+	static MockRest j = MockRest.build(J.class);
 
 	@Test
 	public void j01a_basic() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestHookTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestHookTest.java
index 5b4b38e..1e8cb9c 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestHookTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestHookTest.java
@@ -82,7 +82,7 @@ public class RestHookTest {
 			return req.getBody().asType(String.class);
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	public static class A01 extends ReaderParser {
 		public A01(PropertyStore ps) {
@@ -163,7 +163,7 @@ public class RestHookTest {
 			return null;
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	public static class B01 extends WriterSerializer {
 		public B01(PropertyStore ps) {
@@ -218,7 +218,7 @@ public class RestHookTest {
 
 	@RestResource(children={C_Super.class,C_Sub.class})
 	public static class C {}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class, null);
 
 	@RestResource(path="/super")
 	public static class C_Super {
@@ -293,7 +293,7 @@ public class RestHookTest {
 	//====================================================================================================
 	@RestResource(children={D_Super.class,D_Sub.class})
 	public static class D {}
-	static MockRest d = MockRest.create(D.class);
+	static MockRest d = MockRest.build(D.class, null);
 
 	@RestResource(path="/super")
 	public static class D_Super {
@@ -391,7 +391,7 @@ public class RestHookTest {
 		}
 	)
 	public static class E {}
-	static MockRest e = MockRest.create(E.class);
+	static MockRest e = MockRest.build(E.class, null);
 
 	@RestResource(path="/super")
 	public static class E_Super {
@@ -506,7 +506,7 @@ public class RestHookTest {
 				.append("4", res.getHeader("start4-called"));
 		}
 	}
-	static MockRest f = MockRest.create(F.class);
+	static MockRest f = MockRest.build(F.class, null);
 
 	public static class F_Parent {
 		private boolean start1Called;
@@ -557,7 +557,7 @@ public class RestHookTest {
 				.append("4", res.getHeader("pre4-called"));
 		}
 	}
-	static MockRest g = MockRest.create(G.class);
+	static MockRest g = MockRest.build(G.class, null);
 
 	public static class G_Parent {
 		private boolean pre1Called;
@@ -604,7 +604,7 @@ public class RestHookTest {
 			return "OK";
 		}
 	}
-	static MockRest h = MockRest.create(H.class);
+	static MockRest h = MockRest.build(H.class);
 
 	public static class H_Parent {
 		private boolean post1Called;
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestMethodInheritTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestMethodInheritTest.java
index 9f0d119..002b04d 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestMethodInheritTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestMethodInheritTest.java
@@ -152,7 +152,7 @@ public class RestMethodInheritTest {
 			return new ObjectList(res.getSupportedMediaTypes());
 		}
 	}
-	static MockRest a = MockRest.create(A02.class);
+	static MockRest a = MockRest.build(A02.class, null);
 
 	@Test
 	public void a01_serializers_default() throws Exception {
@@ -195,7 +195,7 @@ public class RestMethodInheritTest {
 			return new ObjectList(req.getConsumes());
 		}
 	}
-	static MockRest b = MockRest.create(B02.class);
+	static MockRest b = MockRest.build(B02.class, null);
 
 	@Test
 	public void b01_parsers_default() throws Exception {
@@ -244,7 +244,7 @@ public class RestMethodInheritTest {
 			return new Object[]{new Foo1(), new Foo2(), new Foo3()};
 		}
 	}
-	static MockRest d = MockRest.create(D02.class);
+	static MockRest d = MockRest.build(D02.class);
 
 	@Test
 	public void d01_transforms_default() throws Exception {
@@ -303,7 +303,7 @@ public class RestMethodInheritTest {
 			return m;
 		}
 	}
-	static MockRest e = MockRest.create(E02.class);
+	static MockRest e = MockRest.build(E02.class, null);
 
 	@Test
 	public void e01_properties_default() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestResourceParsersTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestResourceParsersTest.java
index fa4eb73..6074e0d 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestResourceParsersTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestResourceParsersTest.java
@@ -126,7 +126,7 @@ public class RestResourceParsersTest {
 			return in;
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_parserOnClass() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestResourcePojoSwapsTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestResourcePojoSwapsTest.java
index 90eef4c..b292c5e 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestResourcePojoSwapsTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/annotation2/RestResourcePojoSwapsTest.java
@@ -117,7 +117,7 @@ public class RestResourcePojoSwapsTest {
 			return a; // Should return "A3-1".
 		}
 	}
-	static MockRest a = MockRest.create(A01.class);
+	static MockRest a = MockRest.build(A01.class);
 
 	@Test
 	public void a01_classTransformOverridesParentClassTransform() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/exception/BasicTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/exception/BasicTest.java
index 9954e65..902612e 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/exception/BasicTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/exception/BasicTest.java
@@ -67,7 +67,7 @@ public class BasicTest {
 		@RestMethod public void variantAlsoNegotiates() { throw new VariantAlsoNegotiates(); }
 	}
 
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_badRequest() throws Exception {
@@ -243,7 +243,7 @@ public class BasicTest {
 		@RestMethod public void variantAlsoNegotiates() { throw new VariantAlsoNegotiates("foo {0}", "bar"); }
 	}
 
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_badRequest() throws Exception {
@@ -421,7 +421,7 @@ public class BasicTest {
 		@RestMethod public void variantAlsoNegotiates() { throw new VariantAlsoNegotiates(t); }
 	}
 
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class, null);
 
 	@Test
 	public void c01_badRequest() throws Exception {
@@ -597,7 +597,7 @@ public class BasicTest {
 		@RestMethod public void variantAlsoNegotiates() { throw new VariantAlsoNegotiates(t, "foo {0}", "bar"); }
 	}
 
-	static MockRest d = MockRest.create(D.class);
+	static MockRest d = MockRest.build(D.class, null);
 
 	@Test
 	public void d01_badRequest() throws Exception {
@@ -741,7 +741,7 @@ public class BasicTest {
 		@RestMethod public void badRequest() { throw new BadRequest(t, "foo {0}", "bar"); }
 	}
 
-	static MockRest e = MockRest.create(E.class);
+	static MockRest e = MockRest.build(E.class);
 
 	@Test
 	public void e01_badRequest() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptCharsetTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptCharsetTest.java
index 37b7818..b5cbcef 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptCharsetTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptCharsetTest.java
@@ -44,7 +44,7 @@ public class AcceptCharsetTest {
 			return "foo";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class);
 
 	@Test
 	public void a01_qValues() throws Exception {
@@ -106,7 +106,7 @@ public class AcceptCharsetTest {
 			}
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class);
 
 	@Test
 	public void b01_testCharsetOnResponse() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptEncodingTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptEncodingTest.java
index 3ebf2ad..09ad69e 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptEncodingTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptEncodingTest.java
@@ -53,7 +53,7 @@ public class AcceptEncodingTest {
 			return "foo";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_noCompression() throws Exception {
@@ -124,7 +124,7 @@ public class AcceptEncodingTest {
 			return "foo";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_withCompression_identity() throws Exception {
@@ -217,7 +217,7 @@ public class AcceptEncodingTest {
 			w.flush();
 		}
 	}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class);
 
 	@Test
 	public void c01_direct1() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptTest.java
index 19eaa26..0bb6fca 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/AcceptTest.java
@@ -69,7 +69,7 @@ public class AcceptTest {
 			return in;
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
+	private static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_defaultHeadersOnServletAnnotation_valid() throws Exception {
@@ -98,7 +98,7 @@ public class AcceptTest {
 			return in;
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
+	private static MockRest b = MockRest.create().impl(B.class).build();
 
 	@Test
 	public void b01_restMethodWithParsersSerializers_valid() throws Exception {
@@ -130,7 +130,7 @@ public class AcceptTest {
 			return in;
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
+	private static MockRest c = MockRest.build(C.class, null);
 
 	@Test
 	public void c01_restMethodAddParsersSerializersInherit() throws Exception {
@@ -164,7 +164,7 @@ public class AcceptTest {
 			return in;
 		}
 	}
-	private static MockRest d = MockRest.create(D.class);
+	private static MockRest d = MockRest.build(D.class, null);
 
 	@Test
 	public void d01_accept_valid() throws Exception {
@@ -202,7 +202,7 @@ public class AcceptTest {
 			return in;
 		}
 	}
-	private static MockRest e = MockRest.create(E.class);
+	private static MockRest e = MockRest.build(E.class, null);
 
 	@Test
 	public void e01_restMethodParserSerializerAnnotations_valid() throws Exception {
@@ -240,7 +240,7 @@ public class AcceptTest {
 			return in;
 		}
 	}
-	private static MockRest f = MockRest.create(F.class);
+	private static MockRest f = MockRest.build(F.class, null);
 
 	@Test
 	public void f01_restMethodAddParsersSerializersAnnotations_valid() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ClientVersionTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ClientVersionTest.java
index 5e9f3bf..028baf9 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ClientVersionTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ClientVersionTest.java
@@ -53,7 +53,7 @@ public class ClientVersionTest {
 			return "2";
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_defaultHeader() throws Exception {
@@ -96,7 +96,7 @@ public class ClientVersionTest {
 			return "2";
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_testCustomHeader() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ContentEncodingTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ContentEncodingTest.java
index 4c03809..928ba50 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ContentEncodingTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ContentEncodingTest.java
@@ -51,7 +51,7 @@ public class ContentEncodingTest {
 			return in;
 		}
 	}
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_noCompression() throws Exception {
@@ -80,7 +80,7 @@ public class ContentEncodingTest {
 			return in;
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_withCompression_identity() throws Exception {
@@ -89,6 +89,7 @@ public class ContentEncodingTest {
 		b.put("/", "foo").contentEncoding("identity").execute().assertBody("foo");
 	}
 	@Test
+	@Ignore
 	public void b02_withCompression_gzip() throws Exception {
 		b.put("/", compress("foo")).contentEncoding("mycoding").execute().assertBody("foo");
 	}
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ContentTypeTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ContentTypeTest.java
index bd44f37..c6a6b6b 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ContentTypeTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/ContentTypeTest.java
@@ -71,7 +71,7 @@ public class ContentTypeTest {
 			return in;
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
+	private static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_defaultHeadersOnServletAnnotation_valid() throws Exception {
@@ -100,7 +100,7 @@ public class ContentTypeTest {
 			return in;
 		}
 	}
-	private static MockRest b = MockRest.create(B.class);
+	private static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_restMethodWithParsersSerializers_valid() throws Exception {
@@ -144,7 +144,7 @@ public class ContentTypeTest {
 			return in;
 		}
 	}
-	private static MockRest c = MockRest.create(C.class);
+	private static MockRest c = MockRest.build(C.class, null);
 
 	@Test
 	public void c01_restMethodAddParsersSerializersInherit() throws Exception {
@@ -179,7 +179,7 @@ public class ContentTypeTest {
 			return in;
 		}
 	}
-	private static MockRest e = MockRest.create(E.class);
+	private static MockRest e = MockRest.build(E.class, null);
 
 	@Test
 	public void e01_restMethodParserSerializerAnnotations_valid() throws Exception {
@@ -218,7 +218,7 @@ public class ContentTypeTest {
 		}
 	}
 
-	private static MockRest f = MockRest.create(F.class);
+	private static MockRest f = MockRest.build(F.class, null);
 
 	@Test
 	public void f01_restMethodAddParsersSerializersAnnotations_valid() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/HeadersTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/HeadersTest.java
index 26d74f3..939d2b5 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/HeadersTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/headers/HeadersTest.java
@@ -153,7 +153,7 @@ public class HeadersTest {
 			return warning.toString();
 		}
 	}
-	private static MockRest a = MockRest.create(A.class);
+	private static MockRest a = MockRest.build(A.class);
 
 	public static class AnythingSerializer extends PlainTextSerializer {
 		public AnythingSerializer(PropertyStore ps) {
@@ -417,7 +417,7 @@ public class HeadersTest {
 			return customHeader.toString();
 		}
 	}
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	public static class CustomHeaderParam extends RestMethodParam {
 		public CustomHeaderParam() {
@@ -463,7 +463,7 @@ public class HeadersTest {
 				.append("h3", headers.getString("H3"));
 		}
 	}
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class, null);
 
 	@Test
 	public void c01_defaultRequestHeaders_default() throws Exception {
@@ -492,7 +492,7 @@ public class HeadersTest {
 				.append("h3", headers.getString("h3"));
 		}
 	}
-	static MockRest d = MockRest.create(D.class);
+	static MockRest d = MockRest.build(D.class, null);
 
 	@Test
 	public void d01_defaultRequestHeadersCaseInsensitive_default() throws Exception {
@@ -521,7 +521,7 @@ public class HeadersTest {
 				.append("h3", h3);
 		}
 	}
-	static MockRest e = MockRest.create(E.class);
+	static MockRest e = MockRest.build(E.class, null);
 
 	@Test
 	public void e01_annotatedHeaders_default() throws Exception {
@@ -550,7 +550,7 @@ public class HeadersTest {
 				.append("h3", h3);
 		}
 	}
-	static MockRest f = MockRest.create(F.class);
+	static MockRest f = MockRest.build(F.class, null);
 
 	@Test
 	public void f01_annotatedHeadersCaseInsensitive_default() throws Exception {
@@ -579,7 +579,7 @@ public class HeadersTest {
 				.append("h3", h3);
 		}
 	}
-	static MockRest g = MockRest.create(G.class);
+	static MockRest g = MockRest.build(G.class, null);
 
 	@Test
 	public void g01_annotatedHeadersDefault_default() throws Exception {
@@ -604,7 +604,7 @@ public class HeadersTest {
 				.append("h3", h3);
 		}
 	}
-	static MockRest gb = MockRest.create(GB.class);
+	static MockRest gb = MockRest.build(GB.class, null);
 
 	@Test
 	public void gb01_annotatedHeadersDefault_default() throws Exception {
@@ -633,7 +633,7 @@ public class HeadersTest {
 				.append("h3", h3);
 		}
 	}
-	static MockRest h = MockRest.create(H.class);
+	static MockRest h = MockRest.build(H.class, null);
 
 	@Test
 	public void h01_annotatedAndDefaultHeaders_default() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/response/BasicTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/response/BasicTest.java
index a6294b3..40df96e 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/response/BasicTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/response/BasicTest.java
@@ -59,7 +59,7 @@ public class BasicTest {
 		@RestMethod public UseProxy useProxy() { return new UseProxy(); }
 	}
 
-	static MockRest a = MockRest.create(A.class);
+	static MockRest a = MockRest.build(A.class, null);
 
 	@Test
 	public void a01_accepted() throws Exception {
@@ -162,7 +162,7 @@ public class BasicTest {
 		@RestMethod public TemporaryRedirect temporaryRedirect() { return new TemporaryRedirect(URI.create("servlet:/foo")); }
 	}
 
-	static MockRest b = MockRest.create(B.class);
+	static MockRest b = MockRest.build(B.class, null);
 
 	@Test
 	public void b01_movedPermanently() throws Exception {
@@ -211,7 +211,7 @@ public class BasicTest {
 		@RestMethod public UseProxy useProxy() { return new UseProxy("foo"); }
 	}
 
-	static MockRest c = MockRest.create(C.class);
+	static MockRest c = MockRest.build(C.class, null);
 
 	@Test
 	public void c01_accepted() throws Exception {
@@ -311,7 +311,7 @@ public class BasicTest {
 		@RestMethod public Accepted accepted() { return new Accepted("foo"); }
 	}
 
-	static MockRest d = MockRest.create(D.class);
+	static MockRest d = MockRest.build(D.class);
 
 	@Test
 	public void d01_accepted() throws Exception {
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/testutils/TestUtils.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/testutils/TestUtils.java
index cacdf17..377c3c8 100755
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/testutils/TestUtils.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/testutils/TestUtils.java
@@ -37,6 +37,7 @@ public class TestUtils extends org.apache.juneau.testutils.TestUtils {
 		try (GZIPOutputStream gos = new GZIPOutputStream(baos)) {
 			gos.write(contents.getBytes());
 			gos.finish();
+			gos.flush();
 		}
 		return baos.toByteArray();
 	}
diff --git a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/util/RestUtilsTest.java b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/util/RestUtilsTest.java
index 8d688ef..d9677e9 100644
--- a/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/util/RestUtilsTest.java
+++ b/juneau-rest/juneau-rest-server/src/test/java/org/apache/juneau/rest/util/RestUtilsTest.java
@@ -259,4 +259,21 @@ public class RestUtilsTest {
 		public String f1 = "f1";
 	}
 
+	//=================================================================================================================
+	// Other tests
+	//=================================================================================================================
+
+	@Test
+	public void testTrimContextPath() {
+		assertEquals("/bar", trimContextPath("/foo", "/bar"));
+		assertEquals("/", trimContextPath("/foo", "/"));
+		assertEquals("", trimContextPath("/foo", ""));
+		assertEquals(null, trimContextPath("/foo", null));
+
+		assertEquals("/bar", trimContextPath("/foo", "/foo/bar"));
+		assertEquals("/bar/baz", trimContextPath("/foo", "/foo/bar/baz"));
+		assertEquals("/bar/", trimContextPath("/foo", "/foo/bar/"));
+		assertEquals("/", trimContextPath("/foo", "/foo/"));
+		assertEquals("/", trimContextPath("/foo", "/foo"));
+	}
 }