Introducing restfuse – a JUnit Extension to test REST APIs

For several projects at EclipseSource we are creating REST APIs. I’m involved in most of them and there is one thing that bothers me with every project. That is, testing. I mean, of course we are writing our unit tests first and we mock our services to get fast unit tests, but at some point you also have to make sure that the whole system works with integration tests. And, when writing integration tests for REST APIs in Java, as far as I know, there are currently only two solutions.

The first one is to write plain JUnit tests and do all the requests yourself within the test methods (maybe with the help of utilities). The other option is to use a library called rest-assured. This library provides a kind of DSL for testing REST APIs. You can write your tests with JUnit and use mockito-like syntax to send a request and test the response. But this doesn’t feel like the right solution, because you always have to configure your request with real Java code within your test method. I would prefer a solution where I can simply configure the request using something like annotations and just execute the test after the request is sent.

Another thing that bugs me are asynchronous services. When it comes to handling asynchronous services you always have two options: callbacks or polling. How can I test those services? For polling it’s easier – you can loop the request code – but does this sound right to you? For callbacks you have to open a server, again within your test method or before. It seems there are no cool solutions for this right now – even rest-assured can’t handle these services very well. That’s why I took a little time and tried to solve these problems. The result is a small library called restfuse.

Restfuse is a JUnit extension. It introduces an annotation called @HttpTest which can be used to configure a request. The request is sent before the annotated method is executed as a test method. The response is then injected into the test object and can be used within the test method. It also provides some new asserts like assertNotFound or assertOk to test response codes. A simple @HttpTest looks like this:

@RunWith( HttpJUnitRunner.class )
public class RestfuseTest {
 
  @Rule
  public Destination destination = new Destination( "http://restfuse.com" ); 
 
  @Context
  private Response response; // will be injected after every request
 
  @HttpTest( method = Method.GET, path = "/" )
  public void checkRestfuseOnlineStatus() {
    assertOk( response );
  }  
}

And of course, it also solves the problem with asynchronous services by introducing two annotations called @Callback and @Poll which can be used together with the @HttpTest annotation. For more information on these tests for asynchronous services take a look at the restfuse site.

Restfuse is open source, licensed under the EPL v – 1.0 and is hosted at github. The 1.0 version is also in the Maven Central and online as a p2 repository (yes, it’s an OSGi bundle).  I hope this small library will help you as much as it helped me. I would appreciate feedback on how to make restfuse even better.

followme Introducing restfuse   a JUnit Extension to test REST APIs

9 Responses to “Introducing restfuse – a JUnit Extension to test REST APIs”

  1. Moritz Post says:

    Another similar approach of declaring the REST endpoint is crest. http://crest.codegist.org/

    It is not a unit testing framework but rather a framework to consume REST services declaratively.

  2. Bernhard Jakob says:

    I am not using HttpUnit, because there are too many functions missing. Now I am using the Wink client and write plain JUnit tests and do all the requests myself within the test methods.

  3. So, maybe this is a fit for you ;)
    And if features are missing just report an github issue and we will see what we can do ;)

  4. Alexander Kiel says:

    I think using @RunWith, @Rule and custom annotations is a good way to build a nice DSL inside JUnit. I use the MethodRules and custom annotations myself for various exception matching situations.

    But I ask myself, if it is sufficient to have only constant expressions as in an annotation to specify a HTTP request. I for example use the Jersey Client inside JUnit for may integration tests against a REST API. With the Jersey Client I can use JAXB to build my request entities. So I don’t have to use files as you support them. Having the request entities in external files, can harm readability the whole test case.

    It may be good to have a fluent interface to specify the request inside the test method.

    One other thing: Normally I have to set up a database fixture for my test case. As I setup the database fixture inside the test method, the request would issued to early.

    So there are many things consider. But I have about 1000 tests against a REST API of a application at work with database fixtures. So I’m interested in optimizing them.

  5. Hi Alexander,
    thanks for your feedback. I think you have some valid arguments. But let me discuss one or two.

    Regarding the creation of the POST content within test methods I partly agree. I see the need that the content can be some kind of dynamic. While I created restfuse this was not a need because we are testing our services with a few requests with static content. This is enough because we tested the logic of our services within several normal unit tests. In this unit tests we create dynamic content, but the tests run in-memory. Our integration tests have only one purpose, they should aprove that the system can run. The domain logic and other technical stuff is tested by plain unit tests.

    Regarding the Database Fixture, I don’t get it right I think. You need a client side database to test your services? I can’t see the need for this but please correct me. As I said before, our integration tests are only for one purpose, showing that the system can run. When we have to handle with Databases we do this normally in plain unit tests, doing this over HTTP is to slow for several 1000 tests I believe.

    Cheers Holger

  6. Hi Holger, I’m trying restfuse lib. This lib is really cool for testing REST API.

    currently, I want to make a POST http to rest api, but it not working, could you tell me how i set some field values like this one:

    @HttpTest(method = Method.POST, path = “/mongo/post.php”, content = “status=1″ )
    public void testPost() {
    com.eclipsesource.restfuse.Assert.assertOk(response);
    int responseCode = response.getStatus();
    System.out.println(responseCode);
    System.out.println(response.getBody(String.class));
    }

    thanks !

  7. Hi Trieu,
    I think you need to set request parameters. See https://github.com/eclipsesource/restfuse/issues/8

  8. Fábio Uechi says:

    Hi Trieu,

    I was having the same problem.
    You just need to specify the MediaType and Content parameters.
    For example:

    @HttpTest(
    method = Method.POST,
    path = “/cities”,
    content=”name=Washington&country=US”,
    type= MediaType.APPLICATION_FORM_URLENCODED)
    public void postCityShouldCreateNewCity() {
    assertCreated(response);
    }

  9. julien says:

    can someone explain me how to use restfuse test during maven test phase before installation and deploiement?
    thanks

9 responses so far

Written by . Published in Categories: EclipseSource News, Planet Eclipse, Planet OSGi

Published:
Nov 14th, 2011
Follow:

Twitter Google+ GitHub Facebook