Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

{span:style=
Span
Wiki Markup
style
font-size:2em;font-weight:bold
} JAX-RS Testing{span}
 

Table of Contents

JAX-RS endpoints can be easily tested using the embedded Jetty or CXF Local Transport.

Embedded Jetty

Code Block
languagexmljava
titlejavaMaven Dependency
<dependency>
   <groupId>org.apache.cxf</groupId>
   <artifactId>cxf-rt-transports-http-jetty</artifactId>
   <version>3.0.0</version>
</dependency>

 

 

Code Block
titleExample

import javax.ws.rs.core.Response;

import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;

import org.junit.Test;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;

import custom.MyJaxrsResource;
import custom.Book;

public class JAXRSTest extends Assert {

private final static String ENDPOINT_ADDRESS = "http://localhost:8080/rest";
private final static String WADL_ADDRESS = ENDPOINT_ADDRESS + "?_wadl";
private static Server server;

@BeforeClass
public static void initialize() throws Exception {
     startServer();
     waitForWADL();
}

private static void startServer() throws Exception {
     JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
     sf.setResourceClasses(MyJaxrsResource.class);
        
     List<Object> providers = new ArrayList<Object>();
     // add custom providers if any
     sf.setProviders(providers);
        
     sf.setResourceProvider(MyJaxrsResource.class.class,
                            new SingletonResourceProvider(new MyJaxrsResource(), true));
     sf.setAddress(ENDPOINT_ADDRESS);

     server = sf.create();
}

// Optional step - may be needed to ensure that by the time individual
// tests start running the endpoint has been fully initialized
private static void waitForWADL() throws Exception {
    WebClient client = WebClient.create(WADL_ADDRESS);
    // wait for 20 secs or so
    for (int i = 0; i < 20; i++) {
        Thread.currentThread().sleep(1000);
        Response response = client.get();
        if (response.getStatus() == 200) {
            break;
        }
    }
    // no WADL is available yet - throw an exception or give tests a chance to run anyway
}


@AfterClass
public static void destroy() throws Exception {
   server.stop();
   server.destroy();
}

@Test
public void testGetBookWithWebClient() {
 WebClient client = WebClient.create(ENDPOINT_ADDRESS);
 client.accept("text/xml");
 client.path("somepath"); 
 Book book = client.get(Book.class);
 assertEquals(123L, book.getId());
}

@Test
public void testGetBookWithProxy() {
  MyJaxrsResource client = JAXRSClientFactory.create(ENDPOINT_ADDRESS, MyJaxrsResource.class);
  Book book = client.getBook();
  assertEquals(123L, book.getId());
}
}

...

Starting from CXF 2.6.2 it is possible to use CXF Local Transport for testing the JAX-RS endpoints and clients.
This avoids the need to start an embedded servlet container and the tests will run faster.

Code Block
languagexml
titleMaven Dependency
<dependency>
   <groupId>org.apache.cxf</groupId>
   <artifactId>cxf-rt-transports-local</artifactId>
   <version>3.0.0</version>
</dependency>
Code Block
titleExample
javajava


import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.client.WebClient;
import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;

import org.apache.cxf.transport.local.LocalConduit;

import org.junit.Test;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.AfterClass;

import custom.MyJaxrsResource;
import custom.Book;

public class JAXRSTest extends Assert {

private final static String ENDPOINT_ADDRESS = "local://books";
private static Server server;

@BeforeClass
public static void initialize() throws Exception {
     startServer();
}

private static void startServer() throws Exception {
     JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
     sf.setResourceClasses(MyJaxrsResource.class);
        
     List<Object> providers = new ArrayList<Object>();
     // add custom providers if any
     sf.setProviders(providers);
        
     sf.setResourceProvider(MyJaxrsResource.class.class,
                            new SingletonResourceProvider(new MyJaxrsResource(), true));
     sf.setAddress(ENDPOINT_ADDRESS);

     server = sf.create();
}

@AfterClass
public static void destroy() throws Exception {
   server.stop();
   server.destroy();
}

@Test
public void testGetBookWithWebClientDirectDispatch() {
 WebClient client = WebClient.create(ENDPOINT_ADDRESS);
 WebClient.getConfig(client).getRequestContext().put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);
 
 client.accept("text/xml");
 client.path("somepath"); 
 Book book = client.get(Book.class);
 assertEquals(123L, book.getId());
}

@Test
public void testGetBookViaPipe() {
 WebClient client = WebClient.create(ENDPOINT_ADDRESS);
 client.accept("text/xml");
 client.path("somepath"); 
 Book book = client.get(Book.class);
 assertEquals(123L, book.getId());
}



@Test
public void testAddBookWithProxyDirectDispatch() {
  MyJaxrsResource client = JAXRSClientFactory.create(ENDPOINT_ADDRESS, MyJaxrsResource.class);
  WebClient.getConfig(client).getRequestContext().put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE);
  Book book = client.echoBook(new Book(123));
  assertEquals(123L, book.getId());
}
}

...

Alternatively, the address can be set as a relative value such as "/books", with the server and client transportId attribute set to
"http://cxf.apache.org/transports/local". In this case, when creating the clients, use JAXRSClientFactoryBean:

Code Block
java
java


private static void startServer() throws Exception {
     JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
     sf.setTransportId(LocalTransportFactory.TRANSPORT_ID);
     sf.setAddress("/books");
     sf.setResourceClasses(MyJaxrsResource.class);
     server = sf.create();
}


@Test
    public void testProxyPipedDispatchGet() throws Exception {
        JAXRSClientFactoryBean bean = new JAXRSClientFactoryBean();
        bean.setTransportId(LocalTransportFactory.TRANSPORT_ID);
        bean.setAddress("/books");
        bean.setServiceClass(MyJaxrsResource.class);
        MyJaxrsResource localProxy = bean.create(MyJaxrsResource.class);
        Book book = localProxy.getBook("123");
        assertEquals(123L, book.getId());
    }

 

Mocking HTTP contexts

If you test a code which depends on the injected HTTP contexts such as HttpServletRequest then these contexts will have to be mocked.

For example:

Code Block
JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
sf.setInvoker(new Invoker() {

  Invoker jarsInvoker = new JAXRSInvoker();
  @Override
  public Object invoke(Exchange exchange, Object o) {

   HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
   Mockito.when(request.getRemoteHost()).thenReturn("host");
   exchange.getInMessage().put(AbstractHTTPDestination.HTTP_REQUEST, request);
   return jarsInvoker.invoke(exchange, o);
  }

});