Rest API testing Using Rest Assured:

Monika Vedi
BYJU’S Exam Prep Engineering
6 min readDec 13, 2018

Rest assured is a java based library that is used to test restful web services. We can create highly customizable HTTP Requests to send to the Restful server. This enables us to test wide variety of Request combinations. Rest-Assured library also provides ability to validate the HTTP Responses received from server. For e.g. we can verify the status code, status message, headers and even the body of the response. This makes Rest-Assured a very flexible library that can be used for testing.

For example if your HTTP server returns the following JSON at “https://gorest.co.in/public-api/users?id=3004”:

{
"result": [
{
"id": "3004",
"name": "Narciso Johns",
"gender": "female",
"dob": "1968–06–13",
"email": "fabernathy@reinger.org",
"phone": "(887) 884–0775 x0311",
"website": "http://mohr.com/",
"address": "3145 Clark JunctionsNorth Kallieville, NM 18996",
"status": "inactive",
"_links": {
"self": {
"href": "https://gorest.co.in:443/public-api/users/3004"
},
"avatar": {
"href": "https://lorempixel.com/250/250/people/?99880"
}
}
}
]
}

You can easily use REST Assured to validate interesting things from the response:

@Before
public void setup() {
RestAssured.baseURI = "https://gorest.co.in";
RestAssured.port = 443;
}
@Test
public void givenUrl_whenSuccessOnGetsResponseAndJsonHasRequiredKV_thenCorrect() {
RequestSpecification httpRequest = RestAssured.given();
given().get("/public-api/users id=3004").then().statusCode(200).log().all();
}

REST assured can then help you to easily make the GET request and verify the response. E.g. if you want to verify that id is equal to 2991 you can do like this:

given()
.get("/public-api/users")
.then()
.body("result.id[0]", Matchers.equalTo("2991"))
.log()
.body();

or perhaps you want to check that the id is 3005:

.get("/public-api/users").then().body("result.id", Matchers.hasItem("3005"))

Note: equalTo and hasItems are Hamcrest matchers which you should statically import from org.hamcrest.Matchers.

Hamcrest Matcher:-

Hamcrest is a framework for software tests. Hamcrest allows checking for conditions in your code via existing matchers classes. It also allows you to define your custom matcher implementations.

To use the library for a Maven based project, the following dependency to your pom file:

<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>

The following are the most important Hamcrest matchers:

  1. allOf — matches if all matchers match (short circuits)

2. anyOf — matches if any matchers match (short circuits)

3. not — matches if the wrapped matcher doesn’t match and vice

4. equalTo — test object equality using the equals method

5. is — decorator for equalTo to improve readability

6. hasToString — test Object.toString

7. instanceOf, isCompatibleType — test type

8. notNullValue, nullValue — test for null

9. sameInstance — test object identity

10. hasEntry, hasKey, hasValue — test a map contains an entry, key or value

11. hasItem, hasItems — test a collection contains elements

12. hasItemInArray — test an array contains an element

13. closeTo — test floating point values are close to a given value

14. greaterThan, greaterThanOrEqualTo, lessThan, lessThanOrEqualTo

15. equalToIgnoringCase — test string equality ignoring case

16. equalToIgnoringWhiteSpace — test string equality ignoring differences in runs of whitespace

17. containsString, endsWith, startsWith — test string matching

Syntax:-

The real value of automated tests is realised when they are easy to understand and takes very less effort to maintain them. In the dictionary of REST-assured’s DSL, you can also find constructs for writing in
Given-When-Then style. Using this style helps in specifying pre-conditions under the Given section, behaviour under test under the When section and verifications under the Then section. This helps in maintaining a clear separation of concerns within a test, thus leading to a very readable test

Json schema validation:-

From version 2.1.0 REST Assured has support for Json Schema validation.For example given the following schema located in the classpath as products-schema.json:

{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Product set",
"type": "array",
"items": {
"title": "Product",
"type": "object",
"properties": {
"id": {
"description": "The unique identifier for a product",
"type": "number"
},
"name": {
"type": "string"
},
"price": {
"type": "number",
"minimum": 0,
"exclusiveMinimum": true
},
"tags": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"dimensions": {
"type": "object",
"properties": {
"length": {"type": "number"},
"width": {"type": "number"},
"height": {"type": "number"}
},
"required": ["length", "width", "height"]
},
"warehouseLocation": {
"description": "Coordinates of the warehouse with the product",
"$ref": "http://json-schema.org/geo"
}
},
"required": ["id", "name", "price"]
}
}

You can validate that a resource (/products) conforms with the schema.Hamcrest matcher that can be used to validate that a JSON document matches a given JSON schema. Typical use-case in REST Assured:

get(“/products”).then().assertThat().body(matchesJsonSchemaInClasspath(“products-schema.json”));

matchesJsonSchemaInClasspath is statically imported from io.restassured.module.jsv.JsonSchemaValidator and it's recommended to statically import all methods from this class. However in order to use it you need to depend on the json-schema-validator module by either downloading it from the download page or add the following dependency from Maven:

<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>json-schema-validator</artifactId>
<version>3.2.0</version>
</dependency>

XML Response Verification:-

Not only can it validate a JSON response, it can validate XML as well.

Let’s assume we make a request to http://localhost:8080/employees and we get the following response:

<employees>
<employee category="skilled">
<first-name>Jane</first-name>
<last-name>Daisy</last-name>
<sex>f</sex>
</employee>
</employees>

We can verify that the first-name is Jane like so:

@Test
public void givenUrl_whenXmlResponseValueTestsEqual_thenCorrect() {
post("/employees").then().assertThat()
.body("employees.employee.first-name", equalTo("Jane"));
}

Extracting values from the Response after validation:

You can extract values from the response or return the response instance itself after you’ve done validating the response by using the extract method. This is useful for example if you want to use values from the response in sequent requests. For example given that a resource called title returns the following JSON:-

{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}

and you want to validate that content type is equal to JSON and you also want to extract the title to use that in a subsequent request. This is how:

ArrayList list = given()
.queryParam("id", "1")
.get("https://jsonplaceholder.typicode.com/posts")
.then()
.extract().path("title");
get(list). ..

Header, cookies and status:-

You can also get headers, cookies and status code etc.:-

Response response = get("https://jsonplaceholder.typicode.com/posts");// Get all headers
Headers allHeaders = response.getHeaders();
// Get a single header value:
String headerName = response.getHeader("headerName");
// Get all cookies as simple name-value pairs
Map<String, String> allCookies = response.getCookies();
// Get a single cookie value:
String cookieValue = response.getCookie("cookieName");
// Get status line
String statusLine = response.getStatusLine();
// Get status code
int statusCode = response.getStatusCode();

Specifying response data:-

Besides specifying request parameters you can also specify headers, cookies, body and content type.

Parameter:- REST Assured will automatically try to determine which parameter type (i.e. query or form parameter) based on the HTTP method. In case of GET query parameters will automatically be used and in case of POST form parameters will be used. In some cases it’s however important to separate between form and query parameters in a PUT or POST. You can then do like this:

given().
formParam("formParamName", "value1").
queryParam("queryParamName", "value2").
when().
post("/something");

Multi-value parameter:- Multi-value parameters are parameters with more then one value per parameter name (i.e. a list of values per name).

given().param("myList", "value1", "value2"). ..

or using a list:

List<String> values = new ArrayList<String>();
values.add("value1");
values.add("value2");
given().param("myList", values). ..

Path parameters:- You can also specify so called path parameters in your request, e.g.

post("/reserve/{hotelId}/{roomNumber}", "My Hotel", 23);

Cookies:- In its simplest form you specify cookies like this:

given().cookie("username", "John").when().get("/cookie").then().body(equalTo("username"));

You can also specify a multi-value cookie like this:

given().cookie("cookieName", "value1", "value2"). ..

This will create two cookies, cookieName=value1 and cookieName=value2.

Header:- You can also specify a multi-value headers like this:

given().header("MyHeader", "Something").and(). ..
given().headers("MyHeader", "Something", "MyOtherHeader", "SomethingElse").and(). ..
given().header("headerName", "value1", "value2"). ..

Verifying Response Data:-

You can also verify status code, status line, cookies, headers, content type and body.

Cookies:-

get("/x").then().assertThat().cookie("cookieName", "cookieValue"). ..
get("/x").then().assertThat().cookies("cookieName1", "cookieValue1", "cookieName2", "cookieValue2"). ..
get("/x").then().assertThat().cookies("cookieName1", "cookieValue1", "cookieName2", containsString("Value2")). ..

Status:-

get("/x").then().assertThat().statusCode(200). ..
get("/x").then().assertThat().statusLine("something"). ..
get("/x").then().assertThat().statusLine(containsString("some")). ..

Headers:-

get("/x").then().assertThat().header("headerName", "headerValue"). ..
get("/x").then().assertThat().headers("headerName1", "headerValue1", "headerName2", "headerValue2"). ..
get("/x").then().assertThat().headers("headerName1", "headerValue1", "headerName2", containsString("Value2")). ..

Measuring Response Time:-

As of version 2.8.0 REST Assured has support measuring response time. For example:

long timeInMs = get("/lotto").time()

or using a specific time unit:

long timeInSeconds = get("/lotto").timeIn(SECONDS);

where Seconds is just a standard Timeunit . You can also validate it :-

when().
get("/lotto").
then().
time(lessThan(2000L)); // Milliseconds

or

when().
get("/lotto").
then().
time(lessThan(2L), SECONDS);

Multi-part form data:-

When sending larger amount of data to the server it’s common to use the multipart form data technique. Rest Assured provide methods called multiPart that allows you to specify a file, byte-array, input stream or text to upload. In its simplest form you can upload a file like this:

given().
multiPart(new File("/path/to/file")).
when().
post("/upload");

it will assume a control name called “file”. In HTML the control name is the attribute name of the input tag. To clarify let’s look at the following HTML form:

<form id="uploadForm" action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" size="40">
<input type=submit value="Upload!">
</form>

The control name in this case is the name of the input tag with name “file”. If you have a different control name then you need to specify it:

given().
multiPart("controlName", new File("/path/to/file")).
when().
post("/upload");

--

--