Warp extension for testing RESTful services
jmnarloch Nov 12, 2012 4:43 AMArquillian already allows for deploying JAX-RS services and running them in the client mode like in the provided example:
{code}
@RunWith(Arquillian.class)
public class StockServiceResourceTestCase {
@Deployment
@OverProtocol("Servlet 3.0")
public static Archive createTestArchive() {
return ShrinkWrap.create(WebArchive.class)
.addClasses(StockApplication.class, Stock.class, StockService.class, StockServiceResource.class)
.addAsWebInfResource("web.xml");
}
@ArquillianResource
private URL contextPath;
private StockService stockService;
@BeforeClass
public static void setUpClass() {
RegisterBuiltin.register(ResteasyProviderFactory.getInstance());
}
@Before
public void setUp() {
stockService = ProxyFactory.create(StockService.class, contextPath.toString());
}
@Test
@RunAsClient
public void testGetStock() {
Stock stock = createStock();
ClientResponse response = (ClientResponse) stockService.createStock(stock);
response.releaseConnection();
Stock result = stockService.getStock(1L);
assertEquals("Stock has invalid name.", stock.getName(), result.getName());
assertEquals("Stock has invalid code.", stock.getCode(), result.getCode());
assertEquals("Stock has invalid value.", stock.getValue(), result.getValue());
}
}
{code}
But if we could introduce here Arquillian Warp and it's ability to bind the tests to server lifecycle. We could call a service and run the server assertion directly in REST service execution context.
So what would be Arquillian without another extension. I've started developing Warp extension particular for testing JAX-RS services. The good news is that I had already created a proof of concept that integrates with RESTEasy.
The fallowing test case ilustrates the possible usage:
{code}
@Test
@RunAsClient
public void testWarpGetStock() {
final Stock stock = createStock();
ClientResponse response = (ClientResponse) stockService.createStock(stock);
response.releaseConnection();
Warp.execute(new ClientAction() {
@Override
public void action() {
Stock result = stockService.getStock(1L);
assertEquals("Stock has invalid name.", stock.getName(), result.getName());
assertEquals("Stock has invalid code.", stock.getCode(), result.getCode());
assertEquals("Stock has invalid value.", stock.getValue(), result.getValue());
}
}).verify(new ServerAssertion() {
private static final long serialVersionUID = 1L;
@ArquillianResource
private RestContext restContext;
@AfterServlet
public void testGetStock() {
assertEquals(HttpMethod.GET, restContext.getRequest().getMethod());
assertEquals(200, restContext.getResponse().getStatusCode());
assertEquals("application/xml", restContext.getResponse().getContentType());
assertNotNull(restContext.getResponse().getEntity());
}
});
}
{code}
The ServerAssertion is being run in the web server, where it allows to verify the response before it would be returned to the client. The RestContext is completly artificial entity which stores the current execution context.
There is no generic way to intercept JAX-RS service execution context. This is one of the new features introduced in JAX-RS 2.0, but the standard will need to first become widely supported. The idea for now is to provide suport for concreate implementations.
The target frameworks would be:
- RESTEasy
- Jersey
- CXF
The project is currently hosted here: https://github.com/jmnarloch/arquillian-extension-warp-rest
Anyone would like to join and develop one of the functionalities?