@Test public void testGetCustomerById() { int id = random.nextInt(); Customer expected = new Customer(id); when(customerDao.getById(id)).thenReturn(expected); Customer actual = customerService.getCustomerById(id); assertEquals(expected, actual); }And here's an integration test using the client:
@Test public void testGetCustomerById() { int id = random.nextInt(); Customer expected = new Customer(id); when(customerDao.getById(id)).thenReturn(expected); Customer actual = customerService.getCustomerById(id); assertEquals(expected, actual); }Yup, they're the same test! This makes me happy.
So, how is it done? We'll start with the service interface.
@Path("/customer") public interface CustomerService { @GET @Path("/{id}") @Produces(MediaType.APPLICATION_JSON) Customer getCustomerById(@PathParam("id") int id); }And an implementation that satisfies the unit test above.
public class CustomerServiceImpl implements CustomerService { @Inject CustomerDao customerDao; @Override public Customer getCustomerById(int id) { return customerDao.getById(id); } }Wiring up the unit test is simple, so here's what the integration test looks like in full:
public class CustomerServiceClientTest { // This is the client private CustomerService customerService; // CXF JAX-RS server private Server server; private Random random = new Random(); @Before public void before() { CustomerServiceImpl serviceImpl = new CustomerServiceImpl(); serviceImpl.customerDao = mock(CustomerDao.class); JAXRSServerFactoryBean serverFactory = new JAXRSServerFactoryBean(); serverFactory.setAddress("http://localhost:9090"); serverFactory.setProvider(new JacksonJsonProvider()); serverFactory.setServiceBean(serviceImpl); server = serverFactory.create(); JAXRSClientFactoryBean clientFactory = new JAXRSClientFactoryBean(); clientFactory.setAddress("http://localhost:9090"); clientFactory.setProvider(new JacksonJsonProvider()); clientFactory.setServiceClass(CustomerService.class); customerService = clientFactory.create(); } @After public void after() { service.destroy(); } @Test public void testGetCustomerById() { int id = random.nextInt(); Customer expected = new Customer(id); when(customerDao.getById(id)).thenReturn(expected); Customer actual = customerService.getCustomerById(id); assertEquals(expected, actual); } }The key thing here is the
JAXRSClientFactoryBean
, which creates an implementation of CustomerService
that makes calls to the RESTful service running at localhost:9090
.What this means is that if you publish an artifact containing just the interface, your client-side project can make use of your RESTful service by directly calling the interface methods in Java, hiding the JAX-RS mechanics completely.
2 comments:
What imports do you use
I think these are the relevant ones.
In the service:
import javax.inject.Inject;
import javax.ws.rs.Produces;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.MediaType;
In the test:
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.client.JAXRSClientFactoryBean;
import org.codehaus.jackson.jaxrs.JacksonJsonProvider;
import static org.mockito.Mockito.*;
import static org.junit.Assert.*;
Post a comment