REST Assured Tutorial

In this REST Assured tutorial, you will learn how easy it is to test and validate RESTful APIs. REST Assured provides an excellent HTTP support, explicit verbs, and actions. We will use REST Assured in this tutorial, along with the Hamcrest library to perform assertions.

REST Assured Maven Dependencies

Before we start laying down examples for this library, we need to make a Maven project with the below dependencies. To learn how to create a simple Web Services Project with Maven, check this tutorial Create a Simple Web Service Project with Spring Boot

<dependency>
   <groupId>io.rest-assured</groupId>
   <artifactId>rest-assured</artifactId>
   <version>3.0.0</version>
   <scope>test</scope>
</dependency>
<dependency>
   <groupId>org.hamcrest</groupId>
   <artifactId>hamcrest-all</artifactId>
   <version>1.3</version>
</dependency>
<dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.12</version>
   <scope>test</scope>
</dependency>

The first dependency is for REST Assured, followed by the Hamcrest dependency as we will be using that library as well for assertions. The last dependency is for JUnit.

Find the latest dependencies for REST Assured and Hamcrest on Maven central. We can run a simple maven command to see the dependency tree of the project which will show all dependencies which are present in the project:

mvn dependency:tree

REST-assured dependency tree

Testing with REST Assured Example

To make a simple example, we will take a REST API which returns user profile data to us which is of the form:

{
  "username" : "sergey",
  "password" : "qwerty",
  "email" : "[email protected]",
  "firstName" : "Sergey",
  "lastName" : "Kargopolov",
  "inviteCode" : ["1234", "4567"]
}

Let’s say that this is the JSON response we get when we hit the API:

http://localhost:8080/users/sergey

Check if JSON Key Has a Value

When we write a test case for this API, we will be able to test the content of JSON representation:

import org.junit.Test;

import static io.restassured.RestAssured.get;
import static org.hamcrest.core.IsEqual.equalTo;

public class UserTest {

   @Test
   public void givenUrl_whenSuccessAndJsonHasUsername_thenCorrect() {
       get("/users/sergey").then().statusCode(200).assertThat()
               .body("username", equalTo("sergey"));
   }
}

We first made a GET request to the user and verified if its body actually had a ‘username’ key in the JSON whose value is ‘sergey’. That was easy. But what if you wanted to do a more complex assertion of comparing the ‘inviteCode’ array? Let’s try another example. 

Check If JSON Array has a Value

We can check if JSON Array contains one of the expected values this way:

import org.junit.Test;

import static io.restassured.RestAssured.get;
import static org.hamcrest.CoreMatchers.hasItems;

public class UserTest {

   @Test
   public void givenUrl_whenSuccessAndJsonHasArrayItem_thenCorrect() {
       get("/users/sergey").then().statusCode(200).assertThat()
               .body("inviteCode", hasItems("1234"));
   }
}

JSON Root Data Validation

Suppose we have an array which comprises of primitive values rather than any JSON key-value objects, like:

["Sergey", "Java", "Android", "Firebase"]

This is an anonymous JSON root as it has no key-value pair in JSON data. We can still run validations on this data using the $ symbol. If this data is reachable at endpoint /data, the test will look like:

@Test
public void whenAnonymous_thenCorrect() {
   get("/data").then().statusCode(200).assertThat()
           .body("$", hasItems("Sergey", "Android"));
}

Or a GET statement without any identifier will work equivalently well too:

get("/data").then().statusCode(200).assertThat()
           .body("", hasItems("Sergey", "Android"));

Testing Floats and Doubles with REST Assured

When writing the test cases and using assertions using the REST Assured library for HTTP calls, we need to note that the floating point numbers in the JSON data we get are converted to the primitive type float and this mapping is not interchangeable with double as is the case for many other scenarios in Java.

So, if we have some JSON response data like:

{
  "username" : "sergey",
  "password" : "qwedsa",
  "email" : "[email protected]",
  "firstName" : "Sergey",
  "lastName" : "Kargopolov",
  "credits" : 12.9
}

When we try to test this service against an endpoint, suppose /credits, as:

@Test
public void whenTreatedDouble_thenFail() {
   get("/credits").then().statusCode(200).assertThat()
           .body("credits", equalTo(12.9));
}

he mentioned test-case will fail as the number 12.9 will be treated as a Double and not as a Floating point number. This can be corrected with following representation:

@Test
public void whenTreatedDouble_thenCorrect() {
   get("/credits").then().statusCode(200).assertThat()
           .body("credits", equalTo(12.9F));
}

Explicitly Specifying Request Method

Although we are free to use the static methods as we’ve been using in all above test-cases, we can use a general method and pass in the request method name as String which we want to use for the request.

Let’s have a look at this example:

@Test
public void whenMethodGet_thenOK(){
   when().request("GET", "/users/sergey").then().statusCode(200);
}

This works exactly the same way for other HTTP Methods:

@Test
public void whenMethodPost_thenOK(){
   when().request("POST",
      "/users/sergey").then().statusCode(200);
}

@Test
public void whenMethodOptions_thenOK(){
   when().request("OPTIONS", 
       "/users/sergey").then().statusCode(200);
}

REST Assured BaseURI

In many cases, most of the test cases we write for the Controller layer uses a same Base URI for the APIs. Parameters like these can be set in the config annotated method for the RestAssured class setup method:

@Before
public void setup() {
   RestAssured.baseURI = "http://localhost";
   RestAssured.port = 8080;
}

or

@Before
public void setup() {
   RestAssured.baseURI = "http://localhost:8080";
}

Many other properties can be set in the config method marked with @Before annotations which makes sure that this method is executed before any of the test cases are executed.

Measuring Response Time with REST Assured

One of the most useful features I find for the RestAssured library is that it provides with a very easy way to measure response time for an API we use. This can even be used in the performance-related testing for the APIs which is made much easier with this simple code. Let’s look at an example:

@Test
public void whenMeasureResponseTime_thenCorrect() {
   Response data = RestAssured.get("/users/sergey");
   long timeInMillis = data.time();
   long timeInSec = data.timeIn(TimeUnit.SECONDS);

   assertEquals(timeInSec, timeInMillis/1000);
}

With this simple call for response data and direct methods provided to measure the response time, we can perform many cases with which performance for an API can be audited.

Logging Request Details

The request calls made with the RestAssured library can be easily printed for debugging purposes and even to explore properties which are present in a request object. Here is an example:

@Test
public void whenLogRequest_thenCorrect() {
   given().log().all()
           .when().get("/users/sergey")
           .then().statusCode(200);
}

This request will produce logs on console something like:

Request method:  GET
Request URI:    	 http://localhost:8080/users/sergey
Proxy:                 <none>
Request params:  <none>
Query params:     <none>
Form params:       <none>
Path params:       <none>
Multiparts:     <none>
Headers:        Accept=*/*
Cookies:        <none>
Body:           <none>

I hope this short tutorial on how to test RESTful Web Service endpoints with REST Assured was useful for you. I will publish a few more tutorials on this topic, so stay tuned.

If you like learning new material by following step-by-step video tutorials, check out the below list of video courses. One of them might help you speed up your learning progress.