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
Extractors 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
Extractors used above,
body are function objects,
header is a method that returns a function object for the specified header name.
Extractors can be reuse to implement more complicated
Extractors. 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
Assertions and returns a
Response so generics are not required.
The assertions should be easy to write and should support reusing the logic in the
Extractors. For example reusing the
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.