How to perform CRUD operations REST API testing using Rest Assured in Java

Introduction

In this example we will see how to perform CRUD operations REST API testing using Rest Assured library in Java programming language. Testing and validating REST services in Java is harder than in dynamic languages such as Ruby and Groovy. REST Assured brings the simplicity of using these languages into the Java domain.

This tutorial will show you how to test REST APIs which perform CRUD (Create, Read, Update and Delete) operations. So we will perform testing on HTTP methods GET, POST, PUT and DELETE.

REST Assured can be used easily in combination with existing unit testing frameworks, such as JUnit and TestNG. We are going to use JUnit 5 here. The fluent API used by REST Assured supports the familiar Given/When/Then syntax from behavior driven development (BDD) framework, resulting in a test that is easy to read and takes care of setup, execution, and verification with just a single line of code.

Prerequisites

Eclipse 2019-12, Java at least 8, Rest Assured Library, Junit 5

Note:

  • You should place rest-assured before the JUnit dependency declaration in your pom.xml / build.gradle in order to make sure that the correct version of Hamcrest is used.
  • REST Assured includes JsonPath and XmlPath as transitive dependencies

Build Script or File

If you are using gradle based build tool then you can use below build.gradle script:

plugins {
    id 'java-library'
}

sourceCompatibility = 12
targetCompatibility = 12

repositories {
    jcenter()
}

dependencies {
	//REST Assured
    testImplementation 'io.rest-assured:rest-assured:4.2.0'
    
    //JSON Schema Validator
    implementation 'io.rest-assured:json-schema-validator:4.2.0'

    // Use JUnit test framework
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.6.0'
}

If you are using maven based project then you can use pom.xml file:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	
	<groupId>com.roytuts</groupId>
	<artifactId>crud-restassured-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>
	
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<java.version>at least 1.8</java.version>
	</properties>
	
	<dependencies>
		<dependency>
			<groupId>io.rest-assured</groupId>
			<artifactId>rest-assured</artifactId>
			<version>4.2.0</version>
			<scope>test</scope>
		</dependency>
		
		<dependency>
			<groupId>io.rest-assured</groupId>
			<artifactId>json-schema-validator</artifactId>
			<version>4.2.0</version>
		</dependency>
		
		<dependency>
			<groupId>org.junit.jupiter</groupId>
			<artifactId>junit-jupiter-engine</artifactId>
			<version>5.6.0</version>
			<scope>test</scope>
		</dependency>
	</dependencies>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
                <configuration>
					<source>${java.version}</source>
					<target>${java.version}</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

GET Example

Let’s say URL https://jsonplaceholder.typicode.com/posts returns 100 posts in JOSN format.

[
  {
    "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"
  },
  {
    "userId": 1,
    "id": 2,
    "title": "qui est esse",
    "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"
  },
  {
    "userId": 1,
    "id": 3,
    "title": "ea molestias quasi exercitationem repellat qui ipsa sit aut",
    "body": "et iusto sed quo iure\nvoluptatem occaecati omnis eligendi aut ad\nvoluptatem doloribus vel accusantium quis pariatur\nmolestiae porro eius odio et labore et velit aut"
  },
  {
    "userId": 1,
    "id": 4,
    "title": "eum et est occaecati",
    "body": "ullam et saepe reiciendis voluptatem adipisci\nsit amet autem assumenda provident rerum culpa\nquis hic commodi nesciunt rem tenetur doloremque ipsam iure\nquis sunt voluptatem rerum illo velit"
  },
  {
    "userId": 1,
    "id": 5,
    "title": "nesciunt quas odio",
    "body": "repudiandae veniam quaerat sunt sed\nalias aut fugiat sit autem sed est\nvoluptatem omnis possimus esse voluptatibus quis\nest aut tenetur dolor neque"
  },
  ...
]

Therefore we will test the number of list size or JSON objects or elements. So expected JSON response should have 100 JSON objects in it.

List<Object> list = RestAssured.given().when().get("https://jsonplaceholder.typicode.com/posts").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).extract().body().jsonPath().getList("");

assertEquals(list.size(), 100);

We are performing GET request to retrieve the posts. Then we check the response status code and content type followed by response body extraction as a List. We have used here List type as Object, if you have any predefined class that maps the JSON response then you can use that class.

The above example could be written in the following manner as well:

String response = RestAssured.given().when().get("https://jsonplaceholder.typicode.com/posts").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).extract().response().asString();

list = JsonPath.from(response).getList("");

assertEquals(list.size(), 100);

Let’s say we want to verify the last userId in JSON response is equal to 10:

RestAssured.given().when().get("https://jsonplaceholder.typicode.com/posts").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).body("userId[99]", Matchers.equalTo(10));

Let’s say we want to verify userId has some numbers (1, 2, 3, 4, 10, etc.):

RestAssured.given().when().get("https://jsonplaceholder.typicode.com/posts").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).body("userId", Matchers.hasItems(1, 2, 3, 4, 10));

equalTo and hasItems are Hamcrest matchers which you ideally want to import statically.

You can configure Rest Assured and JsonPath to return BigInteger instead of int and BigDecimal instead of float and double for Json Numbers. For example we can return post id as BigInteger instead of int.

JsonConfig jsonConfig = new JsonConfig(NumberReturnType.BIG_INTEGER);
RestAssured.given().config(RestAssuredConfig.config().jsonConfig(jsonConfig)).when().get("https://jsonplaceholder.typicode.com/posts").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).body("id[99]", Matchers.is(Matchers.equalTo(new BigInteger("100"))));

REST Assured has support for Json Schema validation. For example given the following schema located in the classpath (src/main/resources) as post.json:

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "type": "array",
    "title": "Posts",
    "items": {
        "type": "object",
        "title": "Posts",
        "required": [
            "userId",
            "id",
            "title",
            "body"
        ],
        "properties": {
            "userId": {
                "type": "integer",
                "description": "User id"
            },
            "id": {
                "type": "integer",
                "description": "Post id"
            },
            "title": {
                "type": "string",
                "description": "Post title"
            },
            "body": {
                "type": "string",
                "description": "Post content"
            }
        }
    }
}

We can validate that a resource (https://jsonplaceholder.typicode.com/posts) conforms with the schema:

RestAssured.given().when().get("https://jsonplaceholder.typicode.com/posts").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).body(JsonSchemaValidator.matchesJsonSchemaInClasspath("post.json"));

For schema validation you need json-schema-validator dependency as we have added into our build.gradle or pom.xml file.

Now imagine that you always want to use unchecked validation as well as setting the default json schema version to version 3. Instead of supplying this to all matchers throughout your code you can define it statically. For example:

JsonSchemaValidatorSettings settings = JsonSchemaValidatorSettings.settings().with().jsonSchemaFactory(JsonSchemaFactory.newBuilder().freeze()).checkedValidation(false);

RestAssured.given().when().get("https://jsonplaceholder.typicode.com/posts").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).body(JsonSchemaValidator.matchesJsonSchemaInClasspath("post.json").using(settings));

Now we will find items and verify the results from the API https://reqres.in/api/unknown.

{
	"page": 1,
	"per_page": 6,
	"total": 12,
	"total_pages": 2,
	"data":[
		{"id": 1, "name": "cerulean", "year": 2000, "color": "#98B2D1",…},
		{"id": 2, "name": "fuchsia rose", "year": 2001, "color": "#C74375",…},
		{"id": 3, "name": "true red", "year": 2002, "color": "#BF1932",…},
		{"id": 4, "name": "aqua sky", "year": 2003, "color": "#7BC4C4",…},
		{"id": 5, "name": "tigerlily", "year": 2004, "color": "#E2583E",…},
		{"id": 6, "name": "blue turquoise", "year": 2005, "color": "#53B0AE",…}
	]
}

Let’s say we want to find items which were created before 2002 and assert the names “cerulean” and “fuchsia rose”.

RestAssured.given().when().get("https://reqres.in/api/unknown").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).body("data.findAll {d -> d.year < 2002}.name", Matchers.hasItems("cerulean", "fuchsia rose"));

The other way could be:

String response = RestAssured.given().when().get("https://reqres.in/api/unknown").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).extract().response().asString();

List<String> names = JsonPath.from(response).getList("data.findAll {d -> d.year < 2002}.name");

assertEquals(names.size(), 2);
assertTrue(names.equals(Arrays.asList("cerulean", "fuchsia rose")));

If you have any path parameter then you can pass path parameter in different ways.

RestAssured.given().pathParam("id", 1).when().get("https://jsonplaceholder.typicode.com/posts/{id}")

Or

RestAssured.given().when().get("https://jsonplaceholder.typicode.com/posts/1")

Or

RestAssured.given().when().get("https://jsonplaceholder.typicode.com/posts/{id}", 1)

The example could be written as:

String resp = RestAssured.given().pathParam("id", 1).when()	.get("https://jsonplaceholder.typicode.com/posts/{id}").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).extract().response()
		.asString();

int id = JsonPath.from(resp).getInt("id");
int userId = JsonPath.from(resp).getInt("userId");

assertEquals(id, 1);
assertEquals(userId, 1);

You can pass query parameter as shown below:

String resp = RestAssured.given().queryParam("userId", 1).when().get("https://jsonplaceholder.typicode.com/posts").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).extract().response().asString();

List<Object> list = JsonPath.from(resp).getList("");

assertEquals(list.size(), 10);

If you want query parameter or path parameter will be picked up automatically then you can use just param().

String resp = RestAssured.given().param("userId", 1).when().get("https://jsonplaceholder.typicode.com/posts").then().assertThat().statusCode(200).and().contentType(ContentType.JSON).extract().response().asString();

List<Object> list = JsonPath.from(resp).getList("");

assertEquals(list.size(), 10);

That’s all about GET example and you can always find more at https://github.com/rest-assured/rest-assured/wiki/Usage.

POST Example

HTTP POST method is used generally to create new resource. Let’s say we want to create a new user using REST API https://reqres.in/api/users. The API takes JSON request body as a parameter with name and job parameters in JSON data.

String resp = RestAssured.given().request().accept(ContentType.JSON).body("{\"name\": \"morpheus\", \"job\": \"leader\"}").when().post("https://reqres.in/api/users").then().assertThat().statusCode(201).and().contentType(ContentType.JSON).extract().response().asString();

int id = JsonPath.from(resp).getInt("id");

assertTrue(id > 0);

Let’s say you want to serialize class object as a JSON request then you can use below example. We will again create a new user but this time we will use User object.

public class User {

	private String name;
	private String job;

	//getters and setters

}

Now we will make a call to REST API to create a new user in the server.

User user = new User();
user.setName("morpheus");
user.setJob("leader");

String resp = RestAssured.given().request().accept(ContentType.JSON).body(user).when()
		.post("https://reqres.in/api/users").then().assertThat().statusCode(201).and()
		.contentType(ContentType.JSON).extract().response().asString();

int id = JsonPath.from(resp).getInt("id");

assertTrue(id > 0);

If you have any path parameter in the URI you can use the similar kind of example as we have seen in GET example.

PUT Example

HTTP method PUT generally used to update the existing resource.

Let’s say we want to update our user which is having id 2 using REST endpoint /api/users/2.

String resp = RestAssured.given().request().accept(ContentType.JSON)
	.body("{\"name\": \"morpheus\", \"job\": \"zion resident\"}").when()
	.put("https://reqres.in/api/users/2").then().assertThat().statusCode(200).and()
	.contentType(ContentType.JSON).extract().response().asString();

System.out.println(resp);

String updatedAt = JsonPath.from(resp).getString("updatedAt");

assertTrue(updatedAt != null);

Or using path param:

String resp = RestAssured.given().pathParam("id", 2).request().accept(ContentType.JSON)
	.body("{\"name\": \"morpheus\", \"job\": \"zion resident\"}").when()
	.put("https://reqres.in/api/users/{id}").then().assertThat().statusCode(200).and()
	.contentType(ContentType.JSON).extract().response().asString();

String updatedAt = JsonPath.from(resp).getString("updatedAt");

assertTrue(updatedAt != null);

DELETE Example

HTTP method DELETE is used to delete a resource from server.

Let’s say we want to delete user having id 2.

RestAssured.given().when().delete("https://reqres.in/api/users/2").then().assertThat().statusCode(204);

That’s all about the CRUD operations testing in REST API using Rest Assured library.

Download

Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *