Specification Re-use in Rest-Assured with ResponseSpecBuilder and RequestSpecBuilder

When you are writing tests against your API in Rest-Assured you might have some common expected results that you want to check every single time that you call the API. For example, look at the very simple test below:

@Test
public void testSomeApi()
{
    when().
        get("http://yourWebsiteAddress.com/someAPIcall").
    then().
        statusCode(200).
        body(containsString("Your Website Title"));
}

What this test is doing is calling the ‘someAPIcall’ on ‘http://yourWebsiteAddress.com’ and then checking that the status code of the HTTP response is 200 (for an OK response) and that the body of the response contains a string with “Your Website Title“.

Suppose that you wanted to test lots of API calls on your website. It would probably be reasonable to test that every API call returned a status code of 200 and that the ‘Your Website Title’ string is present in the body of every call. Instead of having to write this into the test each time, you could specify a ResponseSpecBuilder at the top of your test class in a @BeforeClass annotated method like so:

import com.jayway.restassured.builder.ResponseSpecBuilder;
import com.jayway.restassured.specification.ResponseSpecification;
import org.junit.BeforeClass;

import static org.hamcrest.Matchers.containsString;

public class ResponseSpecTest {
    
    public static ResponseSpecBuilder builder;
    public static ResponseSpecification responseSpec;
    
    @BeforeClass
    public static void setupResponseSpecBuilder()
    {
        builder = new ResponseSpecBuilder();
        
        builder.expectStatusCode(200);
        
        builder.expectBody(containsString("Your Website Title"));
        
        responseSpec = builder.build();
    }
}

Now we could re-write the original testSomeApi() test as below:

@Test
public void testSomeApi()
{
    when().
        get("http://yourWebsiteAddress.com/someAPIcall").
    then().
        spec(responseSpec);
}

In all of your subsequent tests in this class, you can then simply make a call to spec(responseSpec) in the then() portion of the request and check for a status code of 200 and for the website title string to be in the body of the request.

You can also do a similar thing if you wish to re-use your request data in different tests. In the test below, we are specifying an Authorization code in our header and a login ID parameter when we make a POST request to our API :

@Test
public void testAnApiPostCall()
{
    given().
        header("Authorization", "abcd-1234-xyz").
        param("loginID", "joebloggs").
    when().
        post("http://yourWebsiteAddress.com/somePostAPI").
    then().
        body("result.message", equalTo("success"));
}

Suppose that every time you made a POST call in your tests you always had to specify the authorization code in the header and the loginID as a parameter. You could specify a RequestSpecBuilder at the beginning of your test code, as in the example below:

import com.jayway.restassured.builder.RequestSpecBuilder;
import com.jayway.restassured.specification.RequestSpecification;
import org.junit.BeforeClass;

public class RequestSpecTest {

    public static RequestSpecBuilder builder;
    public static RequestSpecification requestSpec;

    @BeforeClass
    public static void setupRequestSpecBuilder()
    {
        builder = new RequestSpecBuilder();

        builder.addHeader("Authorization", "abcd-123-xyz");

        builder.addParameter("loginID", "joebloggs");

        requestSpec = builder.build();
    }

}

Now you could re-write your original testAnApiPostCall() test as below, and you could reuse the requestSpec in all of the API calls that require the authorization header and the loginID parameter:

@Test
public void testAnApiPostCall()
{
    given().
        spec(requestSpec).
    when().
        post("http://yourWebsiteAddress.com/somePostAPI").
    then().
        body("result.message", equalTo("success"));
}

I hope that you found this example useful. This functionality is of particular value if you have lots of different APIs to test but they all produce some common results. At a minimum, adding a check to ensure that every API call returns a response code of 200 is useful in itself.

  • Pingback: Testing Bits – 7/19/15 – 7/25/15 | Testing Curator Blog()

  • http://javierseixas.com Javier Seixas

    Hi James! Congrats for your series about Rest assure. I found it out just a few days ago, and its being a very nice way to introduce to its practical use.

    I want to ask you about integration testing and take into account your database while testing API. You have not mention this subject yet, but I hope you can help me anyway.
    When I test a POST method where it is suposed to store some resource in the database, I want to test that the response is correct, for instance that the status is 201, but I also want to test that this resource is persisted in the database, connecting to it and getting the result. Have you faced this problem? How have you solved it? In case not, any idea how you would do it?

    Thanks for you help and opinion. Cheers!

    • http://james-willett.com James Willett

      Hi Javier,

      Thanks for your comment, I am glad you have been finding the series useful.

      Regarding your specific problem, unfortunately it is not one that I have come across. If you want to check that something has been successfully stored in the database, you might need to make an additional API call to check for that.

      For example you might do a POST and send data for the creation of a new user called “Tester123”. You might then need an API that can take a GET call and ask for user “Tester123”, and see what is returned.

      There might be a better way to do it, but thats all I can think of from the top of my head! Maybe someone else will have some more input…

      Hope thats of some help.

      Cheers,

      James

  • Tri

    Hi James,
    Thanks for nice posts. Do you have any tutorial for schema validation?

    • James Willett

      Thanks Tri – I am working on a post for schema validation. It will also be included in the video training course I am developing. Should be released soon!

      • Tri

        Thanks James, that would be great :).

  • Pingback: Groovy GPath in REST Assured - Part 2: GPath JSON()