Monday, 20 May 2013

Testing Multiple HTTP Link Headers with REST Assured

We've recently had a requirement to validate the link headers coming back from a RESTful service as we are trying to be nice and HATEOAS-y because as we know REST APIs must be hypertext-driven.  We're using the REST assured testing framework, which is excellent.

In the following example we're calling a simple GET on a Person resource, the service returns JSON and two link headers to define resources that we can use for navigation.

We're using Jersey's 'declarative hyperlinking' support to define our resources using @Link annotations.  Here's our rather contrived example, this is written in Groovy so hence the square brackets in the annotations:

@Links( [
  @Link(
    value=@Ref( value='people/${instance.id}',
                style=Ref.Style.ABSOLUTE ),
    rel='me'
  ),
  @Link(
    value=@Ref( value='people/${instance.id}/abode/${instance.abode.id}',
                style=Ref.Style.ABSOLUTE,
                condition='${instance.abode != null}'),
    rel='house'
  )
] )
class Dude { 

  Long id
  String forename

  Abode abode
}

The problem we found was around having two headers with the same name i.e. two 'Links'.  We struggled to find any documentation on how to validate these links using REST assured.  After some messing about we came up with this solution, this is a Spock test written in Groovy:

  
def "Fetch a person with rest-assured check link headers"( ) {
   setup:
      grizzly.start()

    when:
      def response = 
        given()
          .header( HttpHeaders.ACCEPT, ContentType.JSON.toString() ).
        expect()
            .statusCode( HttpStatus.SC_OK ).
        when()
            .get( "${BASE_URI}/people/{id}", '10' )
    
      def linkHeaders = extractLinkHeaders( response.headers.getValues( 'Link' ) )

    then:
      linkHeaders.me == 'http://localhost:9998/people/99'
    and:
      linkHeaders.house == 'http://localhost:9998/people/99/abode/98'

    cleanup:
      grizzly.stop()
  }

Other things to note about this test.  We're using an embedded Grizzly server to test the service. The link header values are returned by the call to  response.headers.getValues( 'Link' ).  The extractLinkHeaders() method converts the 'raw' link strings into a Groovy map which makes the testing of the link rel attributes a lot neater.

No comments:

Post a Comment