In part 2, I showed how to describe and execute REST requests with a simple descriptive syntax, but it completely ignored processing the response. This should be as simple as making the request. First let’s simplify access to the components of the response.
You can create a returning
method to execute the Request
and extract one or more values from the Response
. For example:
To implement this, define the generic type Extractor
, this is any function that takes a Response
and returns a value of the generic type T
. Now you can add a returning
method to RichRequestBuilder
. This takes an Extractor
that maps the Response
into the desired value. It also takes an implicit driver
which is required to call the execute
method. This method executes the Request
and passes the Response
to the Extractor
. You can also add overloaded returning
methods taking multiple Extractor
s and returning their results in tuples. This enable multiple values to be returned from a single response. There are versions of returning
that take up to four parameters and return a Tuple4
, more could be added but they should not be required.
Here are some of the Extractor
s used above, statusCode
and body
are function objects, header
is a method that returns a function object for the specified header name.
These Extractor
s can be reuse to implement more complicated Extractor
s. For example you can create a simple json Extractor
using the Play json library.
Most of the time the only reason you require a part of the Response
is to assert on its value, for example using ScalaTest:
The DSL should support this requirement natively. You can add an asserting
method, this will take a sequence of assertion objects, and will verify each one in turn. The asserting
method uses Scala’s varargs syntax to support multiple arguments. The returning
methods could not use this as varargs must all be of the same type. However asserting
just takes a sequence of Assertion
s and returns a Response
so generics are not required.
The assertions should be easy to write and should support reusing the logic in the Extractor
s. For example reusing the statusCode
Extractor
:
To achieve this you can creating a RichExtractor
class that implements the is
method and returns an Assertion
object which, extracts the value on the left-hand-side and compares it to the value on the right-hand-side.
Now the DSL can be used to express the complete testing use case.
This shows how a few simple techniques can be applied to create a reasonably complete DSL for testing REST Web services. The amount of code to implement this DSL is quite small, so the cost-reward ratio is very high. There is one problem, how does a new user of the DSL discover the available syntax? The DSL makes comprehending existing tests quite easy. However modifying them or writing new tests is not so straight forward. While the DSL code is small the interface and ScalaDoc alone are not sufficient to understanding how to apply it (that is, unless you know how the DSL in implemented). I will cover how to documenting the DSL in the next blog post.
The source code for this post is available on github
If you would like to give me any feedback regarding this post I am happy to discuss anything and everything on Twitter and email. If there is enough interest I will also consider enabling comments on my blog.