Class MockRestClient

All Implemented Interfaces:
Closeable, AutoCloseable, HttpClient, HttpClientConnection, HttpConnection, AnnotationProvider

public class MockRestClient extends RestClient implements HttpClientConnection
Mocked RestClient.

This class is used for performing serverless unit testing of @Rest-annotated and @Remote-annotated classes.

The class itself extends from RestClient providing it with the rich feature set of that API and combines it with the Apache HttpClient HttpClientConnection interface for processing requests. The class converts HttpRequest objects to instances of MockServletRequest and MockServletResponse which are passed directly to the call handler on the resource class RestContext.execute(Object,HttpServletRequest,HttpServletResponse). In effect, you're fully testing your REST API as if it were running in a live servlet container, yet not actually having to run in a servlet container. All aspects of the client and server side code are tested, yet no servlet container is required. The actual over-the-wire transmission is the only aspect being bypassed.

The following shows a simple example of invoking a PUT method on a simple REST interface and asserting the correct status code and response body:

Example:

public class MockTest { // A simple bean with one field. public static class MyBean { public int foo = 1; } // Our REST resource to test. // Simply echos the response. @Rest( serializers=Json5Serializer.class, parsers=JsonParser.class ) public static class EchoRest { @RestPut( path="/echo" ) public MyBean echo(@Content MyBean bean) { return bean; } } // Our JUnit test. @Test public void testEcho() throws Exception { MyBean myBean = new MyBean(); // Do a round-trip on the bean through the REST interface myBean = MockRestClient .create(EchoRest.class) .json5() .build() .put("/echo", myBean) .run() .assertStatus().is(200) .assertContent().is("{foo:1}") .getContent().as(MyBean.class); assertEquals(1, myBean.foo); } }

Breaking apart the fluent method call above will help you understand how this works.

@Test public void testEcho() throws Exception { // Instantiate our mock client. MockRestClient client = MockRestClient .create(EchoRest.class) .json5() .build(); // Create a request. RestRequest req = client.put("/echo", bean); // Execute it (by calling RestCallHandler.service(...) and then returning the response object). RestResponse res = req.run(); // Run assertion tests on the results. res.assertStatus().is(200); res.assertContent().is("'foo'"); // Convert the content of the response to a bean. bean = res.getContent().as(MyBean.class); }

The create(Object) method can take in either Class objects or pre-instantiated beans. The latter is particularly useful for testing Spring beans.

The MockRestRequest object has convenience methods provided to allow you to set any properties directly on the underlying HttpServletRequest object. The following example shows how this can be used to directly set roles on the request object to perform security testing.

Example:

@Rest(roleGuard="ADMIN") public class A { @RestGet public String get() { return "OK"; } } @Test public void mytest() throws Exception { MockRestClient client = MockRestClient.build(A.class); // Admin user should get 200, but anyone else should get 403-Unauthorized. client.get().roles("ADMIN").run().assertStatus().is(200); client.get().roles("USER").run().assertStatus().is(403); }

Debug mode is provided that will cause your HTTP requests and responses to be sent to the console:

Example:

MockRestClient client = MockRestClient .create(MyRest.class) .debug() .json5() .build();

The class can also be used for testing of @Remote-annotated interfaces against @Rest-annotated resources.

Example:

// Our remote resource to test. @Remote public interface MyRemoteInterface { @RemoteGet("/echoQuery") public int echoQuery(@Query(name="id") int id); } // Our mocked-up REST interface to test against. @Rest public class MyRest { @RestGet(path="/echoQuery") public int echoQuery(@Query("id") String id) { return id; } } @Test public void testProxy() { MyRemoteInterface client = MockRestClient .create(MyRest.class) .json() .build() .getRemote(MyRemoteInterface.class); assertEquals(123, client.echoQuery(123)); }

Notes:
  • This class is thread safe and reusable.
See Also: