REST-assured HTTP POST and PUT Examples

Learn to make HTTP POST and PUT requests in automated tests with REST-assured. We will learn different ways to customize the request body, headers and authentication. Also, we will learn to verify the API responses.

1. A Simple Example

Before going deeper, let’s start with a simple HTTP POST example to introduce the basic APIs involved in the tests. The following is a POST API and request body.

HTTP POST /users

{
    "name": "lokesh",
    "email": "admin@howtodoinjava.com"
}

A typical API call with sending the request body, headers and verifying the response data is as follows:

@Test
public void createUserWithCustomObject_thenSuccess() throws JSONException {
    given()
        .body(new User("lokesh", "admin@howtodoinjava.com"))
        .header(new Header("x-custom-header", "value"))
        .contentType("application/json")
    .when()
        .post("/users")
    .then()
        .statusCode(201)
        .body("id", notNullValue())
        .body("name", equalTo("lokesh"))
        .body("email", equalTo("admin@howtodoinjava.com"));
}

2. Attaching POST Request Body

REST-assured supports sending the request body in many ways. Some of the most used ways are building JSONObject, parsing a custom object or directly sending the request body from a file. We can imitate a form submission as well.

2.1. Using JSONObject

The JSONObject is from JSON-java library, and REST-assured internally supports it. JSON-java supports parsing JSON documents into Java objects and generating new JSON documents from the Java classes. It can also convert between JSON and XML, HTTP headers, Cookies, and CDL.

To build the JSONObject, we use its put() method similar to Map in Java that takes a key and value. The value can be anything primitives, objects, collections or even Maps. By passing Map and collection, we can build any nested JSON structure.

JSONObject requestParams = new JSONObject();
requestParams.put("name", "lokesh");
requestParams.put("email", "admin@howtodoinjava.com");

given()
    .body(requestParams.toString())
    .contentType("application/json")
.when()
    .post("/users")
.then()
    .statusCode(equalTo(201));

2.2. Using Custom Object

We can pass a custom POJO to the body() method.

User user = new User("lokesh", "admin@howtodoinjava.com");

given()
    .body(user)
    .contentType("application/json")
.when()
    .post("/users")
.then()
    .statusCode(equalTo(201));

The User is a simple POJO without any annotation.

public class User {
  private String name;
  private String email;

  //Setters, getters and constructors
}

To customize the serialization and deserialization, REST-assured support object mappers from GSON, JAXB, Jackson, Faster Jackson and Eclipse Yasson (JSON-B). For example, we can use the Gson annotations in the POJO and then build a GsonObjectMapperFactory with GsonBuilder as follows:

@BeforeAll
public static void setup() {

baseURI = "https://ROOT_URL/";

RestAssured.config = RestAssuredConfig.config()
    .objectMapperConfig(objectMapperConfig().gsonObjectMapperFactory(

        new GsonObjectMapperFactory() {
          @Override
          public Gson create(Type type, String s) {
            return new GsonBuilder()
                .setFieldNamingPolicy(LOWER_CASE_WITH_UNDERSCORES)
                .create();
          }
        }
    ));
}

2.3. Submitting File or InputStream

The body() takes parameters of type java.io.File and InputStream. We can pass on a JSON document directly to the API request. It helps prevent the complexity of parsing the correct JSON document from a POJO. It is sometimes the preferred way among testers who technically are not very efficient.

{
    "name": "lokesh",
    "email": "admin@howtodoinjava.com"
}
given()
    .body(new File("createUser.json"))
    .contentType("application/json")
.when()
    .post("/users")
.then()
    .statusCode(equalTo(201));

3. Adding Request Headers and Query Params

Use accept() and contentType() methods to pass the media-type information.

given()
    .body(...)
    .accept("application/json")
    .contentType("application/json")
    ...

To send query parameters, use the queryParam() method.

given()
    .body(...)
    .queryParam("access-token", "abcd")
    ...

4. Sending Authentication

Passing the authentication information depends on the auth scheme supported by the API. REST-assured supports almost all kinds of authentications OAuth, OAuth2, headers and even form submissions. Use oauth2() for passing the OAuth2 authentication token.

given()
    .auth().preemptive().oauth2(accessToken)
    ...

For adding auth using the headers, AuthFilter is preferred over regular filters or direct headers because AuthFilter is removed when doing given().auth().none() for testing unsecured APIs.

given().
    filter((requestSpec, responseSpec, ctx) -> {
        requestSpec.header("AUTH", "TOKEN");
        return ctx.next(requestSpec, responseSpec);
    }).
when().
        post("/api").
then().
  statusCode(200);

5. Validating Response Status and Body

REST-assured uses functionally rich Hamcrest matchers for verifying the response data. We can verify anything in the response including status codes, headers, cookies, body and even response time.

//Verify status
post("/api").then().assertThat().statusCode(200).
post("/api").then().assertThat().statusLine(containsString("OK")). ..

//Verify headers
post("/api").then().assertThat().header("headerName", "headerValue"). ..
post("/api").then().assertThat().headers("headerName1", containsString("value")). .

//Verify body
given()
    .body(requestParams.toString())
    ...
.when()
    .post("/users")
.then()
    ...
    .body("id", notNullValue())
    .body("name", equalTo("lokesh"))
    .body("gender", equalTo("male"))
    .body("status", equalTo("active"))
    .body("email", equalTo("admin@howtodoinjava.com"))
    ...;

//Verify response time

post("/api").then().time(lessThan(2000L));
post("/api").then().time(lessThan(2L), TimeUnit.SECONDS);

6. Logging and Extracting Response Data

Logging helps in printing useful information about requests and responses so we can debug the test if it does not behave as expected. Rest-assured supports all(), params(), body(), headers(), cookies(), method() and path() methods for logging the specific information, if needed.

  • Use given().log() for building the RequestLoggingFilter used for logging the request data.
  • Use then().log() for logging the response data.
given().log().all() //Log all request specification details
given().log().body() //Log only the request body

post("/api").then().log().all() //Log all response specification details
post("/api").then().log().body() //Log only the request body

In case we want to log the details only if validation fails then we can use ifValidationFails() method.

given().log().ifValidationFails()...
...then().log().ifValidationFails().

REST-assured supports getting the whole response body and even a part of the response document, as well. For getting a specific response part we can use JSON-Path syntax.

InputStream stream = post("/api").asInputStream(); 
byte[] byteArray = post("/api").asByteArray();
String json = post("/api").asString();

String id = given()
        ...
        .post("/users")
    .then()
        ...
        .extract().body().path("user.id");

7. Conclusion

In this tutorial, we learned to test the HTTP POST and PUT APIs using different techniques of sending the custom request body, headers, parameters and authentication tokens. we also learned to process the response data including logging, verifying, extracting and measuring time for performance testing.

Happy Learning !!

Sourcecode on Github

Comments

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode