Versions Compared

Key

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

...

Span
style

font-size:2em;font-weight:bold

...

JAX-RS

...

Testing
 

Table of Contents

JAX-RS

...

endpoints

...

can

...

be

...

easily

...

tested

...

using

...

the

...

embedded

...

Jetty

...

or

...

CXF

...

Local

...

Transport.

Embedded Jetty

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

 

 

Code Block
titleExample

h1. Embedded Jetty

{code:java}
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());
}
}
{code}

It

...

is

...

quite

...

easy

...

to

...

setup

...

a

...

server

...

and

...

start

...

testing

...

it.

...

The

...

advantage

...

of

...

using

...

the

...

embedded

...

Jetty

...

is

...

that

...

a

...

complete

...

end-to-end

...

round-trip

...

can

...

be

...

exercised,

...

thus

...

stressing

...

all

...

the

...

CXF

...

runtime

...

which

...

comes

...

at

...

the

...

cost

...

of

...

some

...

added

...

complexity

...

to

...

do

...

with

...

setting

...

up

...

the

...

server.

...

Local

...

Transport

...

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

{code:java}

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());
}
}
{code}

Note

...

that

...

setting

...

a

...

LocalConduit.DIRECT_DISPATCH

...

property

...

to

...

'true'

...

ensures

...

that

...

the

...

invocation

...

goes

...

immediately

...

into

...

the

...

service

...

chain

...

after

...

the

...

client

...

out

...

chain

...

has

...

completed.

...


If

...

this

...

property

...

is

...

not

...

set

...

then

...

CXF

...

LocalConduit

...

sets

...

up

...

a

...

pipe

...

which

...

is

...

initiated

...

via

...

an

...

initial

...

write

...

on

...

the

...

client

...

side.

...

In

...

the

...

above

...

code

...

example

...

Local

...

transport

...

is

...

activated

...

by

...

using

...

a

...

URI

...

"local:"

...

scheme,

...

for

...

example,

...

"local://books".

...

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


{code: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
{code}

  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);
  }

});