BT

Restfuse 1.0.0 - A Library For Easy REST/HTTP Integration Tests

by Kostis Kapelonis on Nov 25, 2011 |

EclipseSource has released the first stable version for an open source JUnit extension that automates testing of REST/HTTP services. Restfuse is a set of JUnit annotations that, along with the respective HttpJUnitRunner, offer assertions against the response of an HTTP call. Both synchronous and asynchronous remote calls are supported.

Restfuse is already in Maven Central so using it requires no special repository:

<dependency>
    <groupId>com.restfuse</groupId>
    <artifactId>com.eclipsesource.restfuse</artifactId>
    <version>1.0.0</version>
</dependency>

Using the library for synchronous calls is straightforward:

@RunWith( HttpJUnitRunner.class )
public class RestFuseTest {

  @Rule
  public Destination destination = new Destination( "http://example.com" ); 

  @Context
  private Response response; // will be injected after every request

  @HttpTest( method = Method.GET, path = "/reloadLocalConfiguration" )
  public void checkRestfuseOnlineStatus() {
    assertOk( response );
    String answerBody = response.getBody(String.class);
    assertEquals("Expected correct response","done",answerBody);
  }  
}

The test above calls an HTTP endpoint synchronously and then checks for a text-based response (text/plain) with the "done" string. Notice that the first assertOk is a Restfuse assert that checks for the HTTP 200 OK status call while the second assertEquals is the usual string equality assert offered by JUnit. While this endpoint is assumed to return plain text, one could easily parse JSON/XML or something else and perform asserts in a structured manner.

Restfuse also supports asynchronous calls. The canonical example is a long running operation (e.g. progress on a file upload). The client continuously polls the server endpoint in order to gather constant feedback on the actual status. Let's assume a server endpoint that returns a number between 0 and 100 that denotes progress on some operation:

@RunWith( HttpJUnitRunner.class )
public class PollTest1 {

  @Rule
  public Destination destination = new Destination( "http://example.com" ); 

  @Context
  private Response response;
  
  @Context
  private PollState pollState;

  @HttpTest( method = Method.GET, path = "/progressStatus" )
  @Poll( times = 5, interval = 500 )
  public void testAsynchronousService() {
    if(pollState.getTimes() == 5)
    {
	    String answerBody = response.getBody(String.class);
	    assertEquals("Expected last response","100",answerBody);
    }
  }  
}

The test above calls the same endpoint 5 times (with a specified interval) and only on the last call checks the actual HTTP response.

Another interesting feature of the PollState Interface is that it keeps track of all the previous responses at each point in time. This allows for asserts on the history of the calls:

@RunWith( HttpJUnitRunner.class )
public class PollTest2 {

  @Rule
  public Destination destination = new Destination( "http://example.com" ); 

  @Context
  private Response response;
  
  @Context
  private PollState pollState;

  @HttpTest( method = Method.GET, path = "/progressStatus" )
  @Poll( times = 5, interval = 500 )
  public void testAsynchronousService() {
	int currentRun = pollState.getTimes();
	if(currentRun > 1)
	{
		String previousProgress = pollState.getResponse(currentRun - 1).getBody(String.class);
		String presentProgress = response.getBody(String.class);
		assertTrue("Expected some progress",Integer.parseInt(presentProgress) > Integer.parseInt(presentProgress)); //Just for illustration purposes
	}
    }
  }  
}

The test above checks that each response is a higher number than the previous one.

One of the most surprising dependencies of Restfuse is the Jetty HTTP server. The reason for this is that Restfuse also supports asynchronous services that follow the Web Hooks guidelines. Instead of polling multiple times the server, a client endpoint performs a call only once and then waits for a response initiated by the server in a completely different connection. Here is the Restfuse example:

@RunWith( HttpJUnitRunner.class )
public class RestfuseCalbackTest {
 
  @Rule
  public Destination destination = new Destination( "http://example.com" );
    
  @Context
  private Response response;
   
  private class TestCallbackResource extends DefaultCallbackResource {

    @Override
    public Response post( Request request ) {
      assertTrue("Expected a quote response", request.getBody(String.class).startsWith("quote:") );
      return super.post( request );
    }
  }
   
  @HttpTest( method = Method.GET, path = "/requestQuote" )
  @Callback( port = 9090, path = "/asynchron", resource = TestCallbackResource.class, timeout = 10000 )
  public void testMethod() {
    assertAccepted( response );
  }
}

The example above will connect to requestQuote once and then listen to port 9090 of the client. Within 10 seconds it will expect a connection that is text-based and starts with "quote:".

For more extensive information, visit the Wiki, and Javadocs. The source code is hosted on GitHub.

Hello stranger!

You need to Register an InfoQ account or to post comments. But there's so much more behind being registered.

Get the most out of the InfoQ experience.

Tell us what you think

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread
Community comments

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Allowed html: a,b,br,blockquote,i,li,pre,u,ul,p

Email me replies to any of my messages in this thread

Discuss

Educational Content

General Feedback
Bugs
Advertising
Editorial
InfoQ.com and all content copyright © 2006-2013 C4Media Inc. InfoQ.com hosted at Contegix, the best ISP we've ever worked with.
Privacy policy
BT