Grigor Avagyan is an Information Technologies Engineer. He has 12 years of experience in automation engineering, QA and development. Grigor's expertise includes manual and automated testing, continuous integration and Atlassian products.

Learn JMeter in 5 Hours

Start Learning
Slack

Run massively scalable performance tests on web, mobile, and APIs

Jul 06 2017

How to Extract Values When Spring Boot API Testing With REST Assured

The ability to extract values and use them in the following subsequent request is an important ability in modern API Testing solutions. In this blog post I will show you how to extract and assert these values, by using Java, Gradle, Intellij and REST Assured.

 

Intellij is an integrated development environment, REST Assured is an open-source framework for testing REST services in Java, and Gradle is a Build tool. You can choose different tools for this kind of testing. It all depends on your preferences and taste, and of course which kind of project you are testing.

 

For demo testing, I created a small API with Java / Spring Boot and Hibernate. The API has 4 Controllers - Arrival, Departure, Users and Flight. Each of them has 2 or more endpoints/paths for calling by different types of request. Most of them are GET, but there are also POST and DELETE requests in some paths. You can run this test yourself, from here.

 

The testing shown here will cover all simple areas for endpoints testing, e.g. schema validation of JSON response, request time, allowed methods and etc. Unit testing is not included.

 

Step 1 - Create a API Testing Project

 

1. Install IntelliJ IDEA

 

2. Make sure you have JDK installed (at least version 1.8.XXX).

 

Now we will create a new project.

 

3. Open IntelliJ and click “Create New Project”

 

API testing, value extraction

 

4. Select Gradle, Java and the JDK version

 

api testing, value extraction, rest assured

 

5. Name your project

 

api testing, rest assured

 

6. Choose the project destination

 

functional api testing, open-source

 

If you did everything correctly, you should now see this window with an empty Java project:

 

open-source api testing

 

Step 2 - Add Dependencies

 

Now that we have a project, we need to setup the dependencies. You can use these dependencies, since they are public.

 

To do that, double click on your build.gradle file and add the following gradle configuration file:

 

group 'blaze'
version '1.0-SNAPSHOT'

buildscript {
   repositories {
       jcenter()
       mavenCentral()
       maven { url "http://repo.spring.io/libs-snapshot" }
   }
   dependencies {
       classpath("org.springframework.boot:spring-boot-gradle-plugin:1.5.2.RELEASE")
   }
}

apply plugin: 'java'
apply plugin: 'idea'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'org.springframework.boot'

sourceSets {
   main.java.srcDir "src/main/java"
   main.resources.srcDir "src/main/resources"
   test.java.srcDir "src/test/java"
   test.resources.srcDir "src/test/resources"
}

jar {
   baseName = 'blaze-demo-api'
   version =  '1.0'
}

bootRepackage {
   mainClass = 'com.demo.BlazeMetterApi'
}

dependencyManagement {
   imports {
       mavenBom 'io.spring.platform:platform-bom:Brussels-SR2'
   }
}

repositories {
   mavenCentral()
   jcenter()
   maven { url "http://repo.spring.io/libs-snapshot" }
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
   compile group: 'org.springframework', name: 'spring-core'
   compile group: 'org.springframework.boot', name: 'spring-boot-starter-jdbc'
   compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'
   compile group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
   compile group: 'org.springframework.boot', name: 'spring-boot-starter-security'
   compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
   compile group: 'org.springframework.security.oauth', name: 'spring-security-oauth2'
   compile group: 'com.fasterxml.jackson.datatype', name: 'jackson-datatype-hibernate4'
   compile group: 'mysql', name: 'mysql-connector-java'
   compile group: 'io.rest-assured', name: 'rest-assured', version: '3.0.3'
   compile group: 'io.rest-assured', name: 'json-schema-validator', version: '3.0.3'

   testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test'
   testCompile group: 'junit', name: 'junit'
}

 

Step 3 - Write Your Functional API Test Based on REST Assured

 

To start tests via REST Assured, we need to create our first test class. REST Assured provides us with easy and readable API calls and parsing abilities, which is what we want to do.

 

Right click on test/java in IntelliJ -> select New -> Java Class

 

Put in the name ArrivalTest and hit enter. We use this name, because the data that we are going to extract and use is for filling the form of finding flights (as shown in the picture below).

 

api testing with REST assured

 

Let’s write the first test class. This test calls the /arrival API endpoints and executes the following tests:

  • checkArrivalEndpointStatus - check that the endpoint is responding with 200(SC_OK)
  • checkSchemaValidity - check that the response body contains schema valid json
  • checkResponseTimeAll - check that the response time for /all is less than 2000 millis
  • checkResponseTimeById - check that response time for /all is less than 200 millis
  • checkPutMethod - check that the Put method is not allowed
  • checkPostMethod - check that the Post method is not allowed
  • checkDeleteMethod - check that the Delete method is not allowed

 

import org.junit.Test;

import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
import static org.apache.http.HttpStatus.SC_OK;
import static org.hamcrest.Matchers.lessThan;

public class ArrivalTest extends BaseTest {

   @Test
   public void checkArrivalEndpointStatus() {
       prepareGet(ARRIVAL_ALL).statusCode(SC_OK);
   }

   @Test
   public void checkSchemaValidity() {
       prepareGet(ARRIVAL_ALL)
               .assertThat()
               .body(matchesJsonSchemaInClasspath("schemas/arrival_schema.json"));
   }

   @Test
   public void checkResponseTimeAll() {
       prepareGet(ARRIVAL_ALL)
               .time(lessThan(2000L));
   }

   @Test
   public void checkResponseTimeById() {
       prepareGet(ARRIVAL_ALL_BY_ID)
               .time(lessThan(ENDPOINT_RESPONSE_TIME));
   }

   /*
    * Negative testing section
    */
   @Test
   public void checkPutMethod() {
       preparePut(ARRIVAL_ALL_BY_ID, DUMMY_TEST_JSON)
               .then()
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }

   @Test
   public void checkPostMethod() {
       preparePost(ARRIVAL_ALL, DUMMY_TEST_JSON)
               .then()
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }

   @Test
   public void checkDeleteMethod() {
       prepareDelete(ARRIVAL_ALL_BY_ID)
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }
}

 

The second test class will call the /departure API endpoints and execute the following tests:

  • checkArrivalEndpointStatus - check that the endpoint is responding with 200(SC_OK)
  • checkSchemaValidity - check that the response body contains schema valid json
  • checkResponseTimeAll - check that the response time for /all is less than 2000 millis
  • checkResponseTimeById - check that the response time for /all is less than 200 millis
  • checkPutMethod - check that the Put method is not allowed
  • checkPostMethod - check that the Post method is not allowed
  • checkDeleteMethod - check that the Delete method is not allowed

 

import org.junit.Test;

import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
import static org.apache.http.HttpStatus.SC_OK;
import static org.hamcrest.Matchers.lessThan;

public class DepartureTest extends BaseTest {
   @Test
   public void checkDepartureEndpointStatus() {
       prepareGet(DEPARTURE_ALL).statusCode(SC_OK);
   }

   @Test
   public void checkSchemaValidity() {
       prepareGet(DEPARTURE_ALL)
               .assertThat()
               .body(matchesJsonSchemaInClasspath("schemas/departure_schema.json"));
   }

   @Test
   public void checkResponseTimeAll() {
       prepareGet(DEPARTURE_ALL)
               .time(lessThan(ENDPOINT_RESPONSE_TIME));
   }

   @Test
   public void checkResponseTimeById() {
       prepareGet(DEPARTURE_ALL_BY_ID)
               .time(lessThan(ENDPOINT_RESPONSE_TIME));
   }

   /*
    * Negative testing section
    */
   @Test
   public void checkPutMethod() {
       preparePut(DEPARTURE_ALL_BY_ID, DUMMY_TEST_JSON)
               .then()
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }

   @Test
   public void checkPostMethod() {
       preparePost(DEPARTURE_ALL, DUMMY_TEST_JSON)
               .then()
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }

   @Test
   public void checkDeleteMethod() {
       prepareDelete(DEPARTURE_ALL_BY_ID)
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }
}

 

The third test class will call the /flight API endpoints and execute the following tests:

  • checkArrivalEndpointStatus - check that the endpoint is responding with 200(SC_OK)
  • checkSchemaValidity - check that the response body contains schema valid json
  • checkResponseTimeAll - check that the response time for /all is less than 2000 millis
  • checkResponseTimeById - check that the response time for /all is less than 200 millis
  • checkPutMethod - check that the Put method is not allowed
  • checkPostMethod - check that the Post method is not allowed
  • checkDeleteMethod - check that the Delete method is not allowed

 

import org.junit.Test;

import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
import static org.apache.http.HttpStatus.SC_OK;
import static org.hamcrest.Matchers.lessThan;

public class FlightTest extends BaseTest {
   @Test
   public void checkArrivalEndpointStatus() {
       prepareGet(FLIGHT_ALL).statusCode(SC_OK);
   }

   @Test
   public void checkSchemaValidity() {
       prepareGet(FLIGHT_ALL)
               .assertThat()
               .body(matchesJsonSchemaInClasspath("schemas/flight_schema.json"));
   }

   @Test
   public void checkResponseTimeAll() {
       prepareGet(FLIGHT_ALL)
               .time(lessThan(ENDPOINT_RESPONSE_TIME));
   }

   @Test
   public void checkResponseTimeById() {
       prepareGet(FLIGHT_ALL_BY_ID)
               .time(lessThan(ENDPOINT_RESPONSE_TIME));
   }

   /*
    * Negative testing section
    */
   @Test
   public void checkPutMethod() {
       preparePut(DEPARTURE_ALL_BY_ID, DUMMY_TEST_JSON)
               .then()
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }

   @Test
   public void checkPostMethod() {
       preparePost(DEPARTURE_ALL, DUMMY_TEST_JSON)
               .then()
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }

   @Test
   public void checkDeleteMethod() {
       prepareDelete(DEPARTURE_ALL_BY_ID)
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }
}

 

The fourth test class will call the /flight API endpoints and execute following tests:

  • checkArrivalEndpointStatus - check that the endpoint is responding with 200(SC_OK)
  • checkSchemaValidity - check that the response body contains schema valid json
  • checkResponseTimeAll - check that the response time for /all is less than 2000 millis
  • checkResponseTimeById - check that the response time for /all is less than 200 millis
  • checkPutMethod - check that the Put method is not allowed
  • checkPostMethod - check that the Post method is not allowed

 

import org.junit.Test;

import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
import static org.apache.http.HttpStatus.SC_METHOD_NOT_ALLOWED;
import static org.apache.http.HttpStatus.SC_OK;
import static org.hamcrest.Matchers.lessThan;

public class UsersTest extends BaseTest {
   @Test
   public void checkArrivalEndpointStatus() {
       prepareGet(USERS_ALL).statusCode(SC_OK);
   }

   @Test
   public void checkSchemaValidity() {
       prepareGet(USERS_ALL)
               .assertThat()
               .body(matchesJsonSchemaInClasspath("schemas/users_schema.json"));
   }

   @Test
   public void checkResponseTimeAll() {
       prepareGet(USERS_ALL)
               .time(lessThan(ENDPOINT_RESPONSE_TIME));
   }

   @Test
   public void checkResponseTimeById() {
       prepareGet(USERS_ALL_BY_ID)
               .time(lessThan(ENDPOINT_RESPONSE_TIME));
   }

   /*
    * Negative testing section
    */
   @Test
   public void checkPutMethod() {
       preparePut(USERS_ALL_BY_ID, DUMMY_TEST_JSON)
               .then()
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }

   @Test
   public void checkPostMethod() {
       preparePost(USERS_ALL, DUMMY_TEST_JSON)
               .then()
               .statusCode(SC_METHOD_NOT_ALLOWED);
   }
}

 

And finally the last test class will call all the API endpoints based on each other, with the data extractions, and check end to end flow, with the bookFlightEndToEnd test.

 

You can see that the values extracted are “fromCity”, “toCity” and “flightId”.

 

import io.restassured.response.Response;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class ExtractionTest extends BaseTest {

   @Test
   public void bookFlightEndToEnd() {
       String fromCity = prepareGet(DEPARTURE_ALL_BY_ID).extract().path("city");
       String toCity = prepareGet(ARRIVAL_ALL_BY_ID).extract().path("city");

       String jsonCities = "{\"from\":\"" + fromCity +
               "\", \"to\":\"" + toCity +
               "\"}";
       String flightId = preparePost("search", jsonCities).then().extract().path("id");

       String cardNumber = "2864528645765429346";

       String jsonUserData = "{\n" +
               "\t\"name\": \"Greg\",\n" +
               "\t\"address\": \"somewhere\",\n" +
               "\t\"city\": \"yerevan\",\n" +
               "\t\"state\": \"hayastan\",\n" +
               "\t\"zipCode\": \"0006\",\n" +
               "\t\"cardType\": \"master\",\n" +
               "\t\"cardNumber\": \"" + cardNumber + "\",\n" +
               "\t\"cardExpirationMonth\": 9,\n" +
               "\t\"cardExpirationYear\": 20,\n" +
               "\t\"cardNameOnCard\": \"Greg\",\n" +
               "\t\"flightId\": " + flightId + "\n" +
               "}";

       Response resultJson = preparePost("users/", jsonUserData)
               .then()
               .extract().response();

       String cN = resultJson.path("cardNumber");
       int id = resultJson.path("id");
       assertEquals(cardNumber, cN);

       //clean up of DB
       prepareDelete("users/" + id)
               .statusCode(200);
   }
}

 

 

After everything is done, we need to execute all the tests we created. If everything goes fine, we will see following results. If the test would have failed, we would have seen the tests with red circles.

 

api testing with rest assured

 

Congratulations! You have just created and ran your own API test with REST Assured.

 

Looking to automate your API tests? Get your API Testing started with BlazeMeter.

 

Get your website or app ready for Black Friday.

 

Click here to subscribe to our newsletter.

Interested in writing for our Blog?Send us a pitch!

Your email is required to complete the test. If you proceed, your test will be aborted.