{title:'MockRestClient', created:'8.2.0', updated:'9.0.0'}

The {@link oajr.mock.MockRestClient} class is used for performing serverless unit testing of {@link oajr.annotation.Rest @Rest}-annotated and {@link oaj.http.remote.Remote @Remote}-annotated classes.

The {@link oajr.mock.MockRestClient} itself extends from {@link oajr.client.RestClient} providing it with the rich feature set of that API. 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:

| 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 | public static class EchoRest implements BasicRestServlet { | | @RestPut | 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", myBean); | | // 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'"); | | myBean = res.getContent().as(MyBean.class); | }

The concept of the design is simple. The {@link oajr.mock.MockRestClient} class is used to create instances of {@link oajr.mock.MockServletRequest} and {@link oajr.mock.MockServletResponse} which are passed directly to the call handler on the resource class {@link oajr.RestOpInvoker#invoke(RestOpSession)}. 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 create(Object) method can take in either Class objects or pre-instantiated beans. The latter is particularly useful for testing REST APIs written as Spring beans.

| @RunWith(SpringRunner.class) | @ContextConfiguration(classes = {MyApp.class}) | @SpringBootTest | public class MockTest { | | @Autowired | EchoRest echoRest; | | MockRestClient client; | | @Before | public void setup() { | // Instantiate our mock client. | client = MockRestClient | .create(echoRest) | .json5() | .build(); | } | | // 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 = client | .put("/echo", myBean) | .run() | .assertStatus().is(200) | .assertContent().is("{foo:1}") | .getContent().as(MyBean.class); | | assertEquals(1, myBean.foo); | } | }


The {@link oajr.mock.MockRestRequest} object has convenience methods provided to allow you to set properties directly on the underlying {@link jakarta.servlet.http.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); | }


The {@link oajr.mock.MockRestClient} class has a debug mode that will cause your HTTP requests and responses to be sent to the console:

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


The {@link oajr.mock.MockRestClient} class can also be used for testing of {@link oaj.http.remote.Remote}-annotated interfaces against {@link oajr.annotation.Rest @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 | public int echoQuery(@Query("id") String id) { | return id; | } | } | | @Test | public void testProxy() { | MyRemoteInterface mri = MockRestClient | .create(MyRest.class) | .json() | .build() | .getRemote(MyRemoteInterface.class); | | assertEquals(123, mri.echoQuery(123)); | }