Twitter GitHub Facebook Instagram dirv.me

Daniel Irvine on building software

Testing RESTful services with OpenRasta

8 June 2011

This week I’ve been spending time learning OpenRasta, a .NET framework that’s best described as a super-awesome WCF replacement. In fact it kicks WCF’s butt.

OpenRasta helps you write RESTful web services with very little effort. Not just the implementation but your tests too. Unfortunately the testability of OpenRasta-based systems is something of a mystery to beginners like myself, since the test API documentation is non-existent. What follows is how I’ve started out with building my tests.

Assume you’ve got three classes ready to go:

  • a MyResource type, which is your business object
  • a MyResourceHandler, for handling requests to the MyResource resource
  • a Configuration class for initializing OpenRasta.

Normally you’ll also have an ASP.NET project that hosts OpenRasta and your functionality within IIS. That’s what happens at runtime. But for the purposes of testing, you can also host OpenRasta “in memory” without requiring the instantiation of IIS and without the use of “real-life” network resources. You can programmatically fire requests at the in-memory host using a very simple API. Here’s what a barebones test looks like:

using(var host = new InMemoryHost(new Configuration()))
{
  var request = new InMemoryRequest()
    {
      Uri = new Uri("http://localhost/MyResource"),
      HttpMethod = "GET"
    };

  // set up your code formats - I'm using
  // JSON because it's awesome
  request.Entity.ContentType = MediaType.Json;
  request.Entity.Headers["Accept"] = "application/json";

  // send the request and save the resulting response
  var response = host.ProcessRequest(request);
  int statusCode = response.StatusCode;

  // deserialize the content from the response
  MyResource returnedObject;
  if(response.Entity.ContentLength > 0)
  {
    // you must rewind the stream, as OpenRasta
    // won't do this for you
    response.Entity.Stream.Seek(0, SeekOrigin.Begin);

    var serializer = 
        new DataContractJsonSerializer(typeof(MyResource));
    returnedObject = serializer.ReadObject(response.Entity.Stream);
  }
 }

And that’s all there is to it - for a GET operation. If you’re doing a POST, you’ll need to make sure you populate the entity’s Stream and ContentLength properties.

var serializer = new DataContractJsonSerializer(typeof(MyResource));
serializer.WriteObject(Request.Entity.Stream, content);
request.Entity.Stream.Seek(0, SeekOrigin.Begin);
request.Entity.ContentLength = Request.Entity.Stream.Length;

In my own tests I don’t have code that looks exactly like this - I’ve factored it nicely into reusable methods that belong in my test context, and that work across multiple resource types. For example to set up my request I can write

  given_new_request<AnotherResource>(
     "PUT", 
     "AnotherResource",
     anotherResource);

One final, important point. If you’ve designed your classes well, you should be relying on unit tests that do not require OpenRasta to be instantiated at all. Your OpenRasta tests should exist only as end-to-end integration tests and should focus on sending a variety of requests, testing the responses plus any side effects. You should send across a variety of both well-formed and malformed HTTP requests, using the tests to ensure that you stick to REST principles.

About the author

Daniel Irvine is a software craftsman at 8th Light, based in London. These days he prefers to code in Clojure and Ruby, despite having been a C++ and C# developer for the majority of his career.

For a longer bio please see danielirvine.com. To contact Daniel, send a tweet to @d_ir or use the comments section below.

Twitter GitHub Facebook Instagram dirv.me